我有一些关于Promises的问题,这真的让我很困惑。
**.then()方法
在我将进入关于**.then()**方法的困惑之前,我将根据我的知识简要解释JavaScript引擎是如何工作的。
据我所知JavaScript不是一种异步语言,而是一种同步语言
JavaScript引擎同步工作,但Javascript引擎不是浏览器上运行的唯一内容
渲染引擎、setTimeout、HTTP请求等
当我们调用本机函数(例如setTimeout
)时,JavaScript引擎可以与它们对话,因此setTimeout
函数将调用Javascript引擎外部的程序来计时
当然,当计时器结束时,它会将回调发送到事件队列,只有在JavaScript完成所有Execution上下文之后,它才会查看事件队列
好了,现在让我们转到Promises我的问题是.then()
如何知道何时调用resolve()
我读过文章,他们说.then()
异步工作,这对我来说听起来很奇怪,因为JavaScript是同步的,不是吗?也许我没有正确理解他们
所以我对.then()
的工作原理做了自己的假设,因为我还没有找到一个来源,让我有感觉和信心,我知道.then()
是如何工作的。
其中之一(我的假设)是.then
方法中有两个阶段
我将使用这段代码来演示我的假设
var myPromise = new Promise(function(resolve){
resolve('Hello Stackoverflow !');
});
myPromise.then(function(result){
console.log(result);
});
字符串
因此,基于我的假设,resolve('Hello Stackoverflow !')
函数调用.then
方法,.then
检查以下两件事
1.如果.then()
的回调参数被创建
2.如果Promise状态设置为已解决
如果两个条件都为真,那么.then()
方法将把值为Hello Stackoverflow !
的回调插入到事件队列中,只有在所有执行上下文弹出堆栈之后,它才会运行回调,我们将得到结果Hello Stackoverflow !
再次声明,这只是基于我的假设,也许我完全错了。
所以如果你检查我刚才说的,你可以得出结论,.then
方法被调用了两次,为什么?
第一次是resolve函数调用它,但不是所有条件都为真,不为真的是.then
回调参数已创建,但尚未创建,因为我们尚未到达创建回调的代码行,因此条件为假
第二次是当我们调用.then
方法并创建回调时,所有条件都为true,因此它将回调插入事件队列,在所有执行上下文都弹出堆栈后,回调将被调用,我们将获得Hello Stackoverflow !
我希望你能理解我的解释
我说的对不对?
提前感谢大家:)
3条答案
按热度按时间vlurs2pr1#
可以得出
.then
方法被调用了两次的结论这不是真的。
then
方法的呼叫方式与任何方法的呼叫方式相同:当具有该方法调用的语句/表达式在正常执行流中被 * 求值 * 时。示例的同步执行顺序如下所示:
1.回调函数
function(resolve) {...}
被传递给Promise
构造函数。1.此构造函数立即 * 执行 * 它作为参数接收的回调,并将
resolve
和reject
参数传递给它。1.调用
resolve
,并将字符串传递给它。1.因此,实现了
resolve
函数的promise实现会收到通知,并将promise对象的状态设置为已实现,然后注册已实现的值(字符串)。它也会将工作放入[承诺工作]队列中。var myPromise
1.回调函数
function(result) {...}
被传递给myPromise.then()
方法。1.原生
then
实作会注册回呼,但不会执行它。1.本机
then
函数完成执行并返回一个新的promise。您的脚本没有捕获这个返回值,因此我们将这个新的promise标记为promiseB
。1.脚本结束,调用堆栈为空。
现在我们进入通常称为 * 异步 * 执行的部分,它总是从作业/事件队列中的一个条目开始:
1.主机将检查哪些作业队列中有条目,优先级高的作业队列。Promise作业队列具有很高的优先级,通常高于处理用户交互或其他外部事件的事件队列。因此,在上述步骤4中放入队列中的作业将从“承诺作业”队列中取出。
1.执行上述作业。
1.此作业将(逐个)调用已在
myPromise
对象上注册为then
回调函数(如在步骤7中注册的回调函数)。注意:为了简单起见,我忽略了async
/await
语法。1.因此,在本例中,脚本中唯一的
then
回调函数被执行--不要与then
方法本身(在步骤6中已经执行过)混淆。执行then
-回调时,参数为用于实现承诺myPromise
的值(在步骤4中注册的字符串)。1.执行
console.log
。then
回调结束执行并返回undefined
。promiseB
使用此返回值(在本例中为undefined
)来实现。1.作业执行完成。堆栈回退又是空的。
zdwk9cvp2#
Promise的一个非常基本的准系统实现,它可以回答你的问题:
字符串
为了保持简单,我没有考虑链接promise或高级错误处理。但是,当在解析完成之前/之后执行
then
时,这应该可以工作。7kqas0il3#
所以基于我的假设,解析('Hello Stackoverflow!')函数调用
.then
方法,.then
检查以下两项错误,resolve回调不会调用
.then
方法。你首先需要了解Promise是如何工作的。在创建promise对象时,我们为promise构造函数提供了一个执行函数。
字符串
Promise构造器将传递2个参数(即2回调函数)到这个执行函数并调用它。因此,我们编写2个参数(通常命名为resolve,reject)来使用此参数
型
当Promise构造函数调用这个执行函数时,根据你的逻辑,resolve或reject将被调用(带有一个参数)。如果调用resolve,则Promise状态将设置为Fulfiled。否则,如果调用reject,则promise状态将被设置为rejected。
要使用/消费promise,您可以使用promise对象提供的方法,例如:
.then
方法。使用.then
方法时,如果promise处于挂起状态,则.then
方法将回调存储在promise对象中型
否则,如果promise已经被设置,则回调函数将被添加到微任务队列中
**注意:**如果你链接的是另一个
.then
方法,它的回调会被追加到前一个.then
方法返回的新promise对象上.catch
方法的工作方式与.then
方法相同