难以理解 Promise 的工作原理
我有一段代码,可以从本地磁盘获取 JSON 文件:
var modelData = fetch("./modelData.json")
.then((res) => res.json())
.then((val) => console.log(val)
这样做我可以在浏览器控制台中完美地看到 JSON 数据。但是,当我这样做时:
var modelData = fetch("./modelData.json")
.then((res) => res.json())
.then((val) => val)
console.log(modelData)
我在控制台中看到一个 promise(pending)
。我知道异步 JS 是如何工作的,并且我知道链式 then() 仅在前一个承诺得到解决时才会触发。我的问题是,在我的第二个 then() 块中,为什么当我 console.log() 时可以看到数据,但当我从 console.logging 的同一函数返回它时看不到日期?
另外,如果我考虑到这样一个事实,即在第二种情况下,当我 console.logged 时,由于 fetch() 的异步性质,承诺没有得到履行,我尝试了以下操作:
var modelData = fetch("./modelData.json")
.then((res) => res.json())
.then((val) => val)
setTimeout(()=>console.log(modelData), 1000)
认为一旦承诺得到履行,我肯定会得到我的价值。但后来我明白了
承诺(兑现)
。谁能告诉我我错过了什么?我将非常感谢任何帮助。
I have a piece of code where I fetch a JSON file from my local disk:
var modelData = fetch("./modelData.json")
.then((res) => res.json())
.then((val) => console.log(val)
And doing this I can perfectly see the JSON data in my browser console. However when I do this:
var modelData = fetch("./modelData.json")
.then((res) => res.json())
.then((val) => val)
console.log(modelData)
I see a promise(pending)
in my console. I know how async JS works, and I know that the chained then() fires only when the previous promise is resolved. My question is, in my second then() block, why can I see the data when I console.log() it but cant see the date when I return it from the same function where I was console.logging it?
Also, if I consider the fact that maybe in the second case the promise wasnt fulfilled when I console.logged it, due to the async nature of fetch(), I tried the following:
var modelData = fetch("./modelData.json")
.then((res) => res.json())
.then((val) => val)
setTimeout(()=>console.log(modelData), 1000)
thinking that once the promise is fulfilled, I will surely get my value. But then I get
Promise(fulfilled)
. Can anyone tell me what I am missing? I will be really grateful for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一开始理解这个概念很困难。我将稍微更改您的代码:
如您所见,是相同的代码。我做出承诺并设定决心后要做的事情。您得到的是一个对象(承诺),它将运行您的提取,并在成功时调用您的“then”函数。
但变量“promise”(问题中的 modelData)始终是一个承诺。从来没有关于您的模型的数据。
想象一下,您调用某个延迟 60 秒的 setTimeout 函数,而不是 fetch。你的 console.log 将立即执行,在那一刻你不可能得到你的函数的结果,除了对象是一个承诺,而不是你获取的数据。
但是调试代码,想象一下你输入了promise代码,60秒后,你进入了“then”函数。在该函数内部,您可以获取数据。为此,您可以在 then 函数内部处理结果,而不是在外部。
It's difficult at first understanding this concepts. I'm going to change a bit your code:
As you see, is the same code. I create a promise and set what I want to do when become resolved. That you get is an object (the promise) that will run your fetch and, on success, will invoke your "then" funcion.
But the variable "promise" (modelData in your question) is always a promise. Never has data about your model.
Imagine that instead of fetch, you invoke some setTimeout function with 60 seconds of delay. Your console.log is going to be exectuted inmediatly and it's impossible that in that moment you have the results of your funcion, apart from that the objct is a promise, not your fetched data.
But debug the code, imagine that you enter into the promise code and after 60 seconds, you enter in the "then" function. Inside that function is where you have available your data. It's for that what you work with the results inside the then function, never outside.
你无法“拆开” Promise,但你甚至不必这样做。
Promise 并不是真实数据的占位符,一旦数据到达就会神奇地变成它。它是一个句柄,通过它您可以以相同的方式访问数据,无论数据是已经到达还是稍后到达。
因此,从
then
回调返回的任何内容都将始终包装在另一个 Promise 中,因此仍然无法从外部直接访问它。如果我们有以下代码,
...我们可以像这样可视化结构:
正如您所看到的,需要另一个
.then
来访问p3
。这就是为什么
console.log
在内部then
可以打印真实值,而console.log
在外部只会给你一个承诺。You can't "unwrap" a Promise, but you shouldn't even have to.
A Promise is not a placeholder for the real data that will magically turn into it once it arrives. It's a handle, through which you can access the data the same way no matter if it has already arrived or will only arrive later.
For that reason, anything returned from a
then
callback will always be wrapped in another promise, so that it's still not possible to directly access it from the outside.If we have the following code,
...we can visualise the structure like this:
As you can see from that, another
.then
would be required to access the value inp3
.That is why
console.log
ging inside athen
can print the real value, whileconsole.log
ging outside will only give you a promise.fetch()
函数和then()
方法都返回一个Promise
对象。您将该Promise
对象分配给modelData
,它将保留为Promise
对象,并且不会自动重新分配给已实现的值。要获取已完成的值,您可以使用
then()
方法或await 关键字
。The
fetch()
function andthen()
method both return aPromise
object. You assigned thatPromise
object tomodelData
and it will stay as aPromise
object and will not be reassigned to the fulfilled value automatically.To get the fulfilled value, you could either use the
then()
method orawait keyword
.你可以这样做
Promise(fulfilled)
的原因是因为 javascript 运行同步而不是异步,所以你需要像上面一样链接 .then 或在异步块中运行它。You can do it like this
The reason for
Promise(fulfilled)
is because javascript runs sync instead of async so you would need to chain .then like above or run it in an async block.如果您确实想要执行基于 setTimeout() 的方法,那么以下方法可能会起作用(这完全取决于承诺需要多长时间才能实现)。
但最终这并不比简单地将 console.log() 放入最终的.then() 中更容易。通过这种方法,您可以确保在履行承诺后立即得到结果。而且,作为奖励,收到的结果将可用于全局变量
modelData
中进一步的事件驱动交互。If you really want to do a
setTimeout()
based approach then the following will probably work (it all depends on how long the promise will take to be fulfilled).But in the end this is not any easier than simply placing your console.log() into the final
.then()
. With this approach you can be sure to get the result as soon as the promise is fulfilled. And, as a bonus, the received result will be available for further event-driven interactions in the global variablemodelData
.