我只是想提高我对JavaScript Promises如何工作的理解.我创造了以下情况:
LOG 'FOO'
RUN CALLBACK LOGGING 'CALLBACK'
LOG 'BAR'
期望所有功能立即完成(我的意思是他们不会花费过多/未知的时间来完成您将使用异步操作来完成),以便上述操作顺序将按此顺序发生.
您可以通过以下方式编写此代码:
function foo(cb) {
// LOG 'FOO'
console.log('foo');
// RUN CALLBACK
cb();
}
function callback() {
// LOG 'CALLBACK'
console.log('callback');
}
foo(callback);
console.log('bar');
这会根据我在开头指定的情况产生预期的输出.
> foo
> callback
> bar
您也可以通过以下方式编写它:
function foo() {
return new Promise((resolve) => {
// LOG 'FOO'
console.log('foo');
return resolve(null);
});
}
function callback() {
// LOG 'CALLBACK'
console.log('callback');
}
foo().then(callback);
// LOG 'BAR'
console.log('bar');
这种情况会产生以下结果:
> foo
> bar
> callback
这是我不清楚的地方,因为我期待foo立即完成,以便回调将运行并在条形日志’bar’之前记录’回调’
解决方法:
相关规格如下:
onFulfilled
oronRejected
must not be called until the execution context stack contains only platform code. [3.1].
并注意3.1(强调我的):
Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that
onFulfilled
andonRejected
execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such assetTimeout
orsetImmediate
, or with a “micro-task” mechanism such asMutationObserver
orprocess.nextTick
. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.
> ECMAScript 6.0(基于Promises / A)有点难以清晰地摘录,但后来解决了as in section 25.4.5.3.1:
Else if the value of promise‘s [[PromiseState]] internal slot is
"fulfilled"
,a. Let value be the value of promise‘s [[PromiseResult]] internal slot.
b. Perform EnqueueJob(
"PromiseJobs"
, PromiseReactionJob, «fulfillReaction, value»).Else if the value of promise’s [[PromiseState]] internal slot is
"rejected"
,a. Let reason be the value of promise‘s [[PromiseResult]] internal slot.
b. Perform EnqueueJob(
"PromiseJobs"
, PromiseReactionJob, «rejectReaction, reason»).
重要的EnqueueJob操作定义于section 8.4 (“Jobs and Job Queues”),其前言(粗体是我的):
Execution of a Job can be initiated only when there is no running execution context and the execution context stack is empty. […] Once execution of a Job is initiated, the Job always executes to completion. No other Job may be initiated until the currently running Job completes.
在实践中,这可以让您做出一些简单而一致的陈述:
>你可以指望当时或捕捉(等)总是异步行为,从不同步.
>即使在另一个Promise中明确解析了一个Promise,你也永远不会在同一个堆栈上看到多个then或catch处理程序.这也意味着递归Promise执行不会像正常的函数调用那样冒着堆栈溢出的风险,尽管如果你在病态情况下不小心使用递归闭包,你仍然可以用尽堆空间.
>在then或catch处理程序中排队的耗时操作将永远不会阻塞当前线程,即使Promise已经解决,因此您可以排队多个异步操作而不必担心订单或承诺状态.
>即使在已经解决的Promise上调用,也不会在then或catch之外有一个封闭的try块,因此对于平台是否应该处理抛出的异常没有任何歧义.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。