我有以下内容
return this
.configure(config => {
viewModel.configure(config, this);
return config;
})
.then(() => {
this.activate();
});
,相当于以下代码块,由vscode auto promise-> async / await转换建议:
await this.configure(config => {
viewModel.configure(config, this);
return config;
});
this.activate();
我的问题是,他们的时间实际上是否相同?在promise示例中,then()
1个微任务中的第二个fn是否不应该远离接受config
的回调?
为清楚起见,还有一个额外的问题:在计时角度上,以下条件是否相等:
Promise.all(tasks)
.then(() => {
othertasks.forEach(() => doStuff());
})
.then(() => {
prune();
});
和:
await Promise.all(tasks);
othertasks.forEach(() => doStuff();
await Promise.resolve();
prune();
答案 0 :(得分:2)
编辑:关于Andrea Giammarchi的回答,我应该澄清一下,我的回答纯粹是并且仅与同步之间的
在我和bigopon在github问题中进行讨论的情况下,这更有意义,他接受了VS Code的建议,该建议从一段遗留代码中从承诺链中删除“冗余” .then
碰巧对细微的计时问题很敏感。
我指出,此更改将使特定方法提前一秒钟执行,而这种影响可能会破坏依赖于这些(古怪)时间的复杂应用程序。
当时的讨论是这样的,
somePromise.then(() => {
...
}).then(() => {
doStuff();
})
将具有与此相同的时间:
await somePromise;
doStuff();
我的回答是:不,第二个摘录中的doStuff()
会提前执行一个滴答声。
如果有人建议await
或.then
实际上会被同步执行(如果传递的诺言已经解决的话),那激励我写这个答案并阐明为什么不这样做。
我确实意识到,没有这种上下文,我的回答似乎会引起误解,但同样:只是指出了滴答声的相似性。
以简单的方式解析值:
await something
等效于此:
Promise.resolve(something).then()
它们都导致未完成的承诺。
对于排队任务,此:
await Promise.resolve();
doStuff();
等效于此:
Promise.resolve().then(() => {
doStuff();
})
在两种情况下,doStuff()
都发生在下一个刻度上。
要确定常规.then
链是否等效于一系列await
,只需计算.then
和await
。如果在两个给定的代码段中每个代码的数量相同,那么在这些代码段之间传递的时间/滴答声/时间将是相同的。
另一个例子,这是
await Promise.resolve();
doStuff();
await Promise.resolve();
doStuff();
await Promise.resolve();
await Promise.resolve();
doStuff();
等效于此:
Promise.resolve()
.then(() => {
doStuff();
})
.then(() => {
doStuff();
})
.then(() => {})
.then(() => {
doStuff();
})
请注意,Promise.resolve()
本身对时间没有影响。它返回一个已解决的承诺。是then()
/ await
使其变为待处理的文件。
因此,我谨对此表示不同意,我相信您的两个例子都是相同的。
如果答应。[[PromiseState]]是“待处理”,则
a。将promiseReaction追加为诺言的列表的最后一个元素。[[PromiseFulfillReactions]]。
b。追加rejectReaction作为诺言的List的最后一个元素。[[PromiseRejectReactions]]。
否则,如果诺言。[[PromiseState]]被“履行”,则
a。让价值成为承诺。[[PromiseResult]]。
b。执行EnqueueJob(“ PromiseJobs”,PromiseReactionJob,«complementReaction,value»)。
这是“如果诺言已经悬而未决,只需附加该悬而未决的诺言的complementReaction,但诺言已兑现,然后加入新工作”。
换句话说,保证.then
返回一个待处理的承诺,无论它所链接的承诺是否已实现。
答案 1 :(得分:1)
我认为VSCode所发生的事情,您作为问题提出的问题以及收到的答案的类型都存在很多困惑。
我会尽力澄清所有问题,希望我能正确解决这个问题。
让我开始说...
这两个块不相等
以下代码:
this
.configure(config => {
viewModel.configure(config, this);
return config;
})
.then(value => `some ${value}`);
仅与该名称“ 等效”
await this
.configure(config => {
viewModel.configure(config, this);
return config;
})
.then(value => `some ${value}`);
这是因为await
的优先级低于方法链接/ then
的串联。
(async function (){
const then = await Promise.resolve(1).then(one => one + one);
console.log(then); // this is number 2
const something = await 123;
console.log(something); // this is number 123
}());
您应该感到困惑的原因是VSCode超越了您的意图。
return this
.configure(config => {
viewModel.configure(config, this);
// configure() returns a Promise
// and config can be a Promise too
return config;
})
.then(() => {
// but you are not using here the config value
// or, if it was a promise, whatever value it resolved
// and you are also not returning any value
this.activate();
});
由于VSCode知道configure
是 thenable ,并且它的返回值也可能是Promise,这意味着activate
仅在config
之后才会发生最终解决,它也知道用extra
勾号是没有意义的,因为您不需要返回任何config
(无论是价值还是承诺),因此activate
可以被称为正确离开。
由于您在最后一个then
中也未返回任何值,因此可以删除整个return
。
// only async to wait for
await this.configure(config => {
viewModel.configure(config, this);
return config;
});
// with config either value or promise
// there's nothing else to wait for, so
// let's invoke activate without returning
// anything, producing is the same undefined result
this.activate();
回顾一下等待中发生的事情:
(async function (){
const config = new Promise(res => setTimeout(res, 1000));
console.time('awaiting');
const value = await Promise.resolve(1).then(() => {
return config;
});
console.timeEnd('awaiting');
// awaiting: 1000.XXXms
}());
如果您有机会在最后一个then
中使用返回值,您将发现VSCode无法删除它,最有可能将其重新命名为const value = await ...; this.activate(value);
,这仍然可以
在上一条评论中指出:
以简单的方式解析值:
await something
等效于此:
Promise.resolve(something).then()
它们都导致未完成的承诺。
不确定我读错了什么,但对我来说这是一个令人误解的陈述。
const resolved = await anything
表示resolved
始终是一个值,而不是未完成的承诺。
这很可能是await
的全部要点:它不会停止等待,直到有一个值为止。
示例:
(async function (){
const something = Promise.resolve(Math.random());
// this logs the random number as typeof number
console.log(await something);
// this also logs the random number as typeof number
console.log(await Promise.resolve(something).then());
// while this is one is the only pending promise
console.log(Promise.resolve(something).then());
}());
您最终在控制台中看到Pending promise的原因是AIIFE(异步立即调用函数表达式)本身就是一个Promise,您可以在其他地方等待它。
您会看到,返回值或未完成的承诺将始终产生预期的结果。
(async function (){
// instant return, it's just fine
// return 123;
// return promise (unnecessary ticks added)
return Promise.resolve(123).then();
}()).then(console.log);
在两种情况下都记录123
号。
我希望现在很清楚,特别是对于OP,VSCode中发生了什么,特别是为什么发生了。
致谢。