【问题标题】:How do Promises handle immediate resolution?Promises 如何处理立即解决?
【发布时间】:2018-03-21 00:47:34
【问题描述】:

用 Promises 做实验,发现了一些我没想到的东西。

function Delayer(time){
	return new Promise((resolve,reject)=>{
		if(time != 0){
			setTimeout(()=>resolve("Waited " + (time/1000) + " secs!"),time)
		}
		else{
			resolve("No Time Waited");
		}
	})
}
var output = "Promise not resolved yet!";
console.log(output);
Delayer(10).then(function(msg){output = msg; console.log(output)});
console.log(output);//this wont change until callback.
Delayer(0).then(function(msg){output = msg; console.log(output)});
console.log(output);

我希望这个 Promise 像这样解决:

> Promise not resolved yet!
> Promise not resolved yet!
> No Time Waited
> No Time Waited
> Waited 3 secs!

相反,我得到 3 个“尚未解决”,只有一个“没有时间等待”。在处理立即解析之前,它显然要等到其余代码完成。它是如何做到的?

在创建可立即解决的 Promise 时,设计最佳实践是什么?

【问题讨论】:

  • 如果您接受异步,请真正接受它。不要试图区分你认为异步的函数可能是立即的。处理它们的方式与处理在未知时间内解决的问题相同。
  • 我创建这个例子只是为了突出这个特性。我不希望这会导致我的代码出现问题,只是想知道它是如何工作的。我实际上预计这会导致问题,但这证明我错了。

标签: javascript promise


【解决方案1】:

Promise 规范要求它们始终异步调用回调,即使 Promise 已经处于已解决状态。这是一个非常有益的品质,因为您可以确保您的代码将始终以相同的顺序执行,无论它是否必须等待。如果 promise 有时会同步调用回调,那么执行顺序将取决于 promise 的内部状态,可能会导致 bug。

具体参见Promise a+ spec 的要求 2.2.4:

在执行上下文堆栈仅包含平台代码之前,不得调用onFulfilledonRejected

【讨论】:

  • promisesaplus.com/#point-34 谢谢。它是如何做到的? (或者这是一个我不应该担心的问题?)
  • Will Sentance 有一个关于 JavaScript 的 "The Hard Parts" 的精彩课程,他在其中详细说明了执行上下文堆栈如何与前端大师上的异步代码一起工作
  • @GreenFox 基本上,.then 函数内的代码是 if(isAlreadyResolved) {setImmediate(() => callback())} 而不是 if(isAlreadyResolved) {callback()}
猜你喜欢
  • 2015-02-10
  • 2015-02-09
  • 2018-11-17
  • 2014-08-06
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
相关资源
最近更新 更多