在ES6 JavaScript中,为什么then()的实现处理程序返回的承诺与then()返回的承诺不同?
我有一些方块从页面上滑下,以链式的方式: 代码是:在ES6 JavaScript中,为什么then()的实现处理程序返回的承诺与then()返回的承诺不同?,javascript,es6-promise,Javascript,Es6 Promise,我有一些方块从页面上滑下,以链式的方式: 代码是: new Promise(function(resolve, reject) { $("#shape").css({ top: 100 }); setTimeout(function() { resolve(); }, 1000); }).then(function() { return new Promise(function(resolve, reject) { $("#shape2").css(
new Promise(function(resolve, reject) {
$("#shape").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
return new Promise(function(resolve, reject) {
$("#shape2").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
});
}).then(function() {
return new Promise(function(resolve, reject) {
$("#shape3").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
});
}).then(function() {
return new Promise(function(resolve, reject) {
$("#shape4").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
});
});
let foobar;
let lala = new Promise(function(resolve, reject) {
$("#shape").css({
// ...
}).then(function() {
foobar = new Promise(function(resolve, reject) {
// ...
return foobar;
});
lala.then(function() {
console.log("checking:", lala, foobar, lala === foobar);
return new Promise(function(resolve, reject) {
(代码在这里的代码片段中运行不太好:这里第一个方块已经开始向下滑动)
因此,要查看履行处理程序返回了什么承诺,以及返回了什么承诺
代码是:
new Promise(function(resolve, reject) {
$("#shape").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
}).then(function() {
return new Promise(function(resolve, reject) {
$("#shape2").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
});
}).then(function() {
return new Promise(function(resolve, reject) {
$("#shape3").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
});
}).then(function() {
return new Promise(function(resolve, reject) {
$("#shape4").css({
top: 100
});
setTimeout(function() {
resolve();
}, 1000);
});
});
let foobar;
let lala = new Promise(function(resolve, reject) {
$("#shape").css({
// ...
}).then(function() {
foobar = new Promise(function(resolve, reject) {
// ...
return foobar;
});
lala.then(function() {
console.log("checking:", lala, foobar, lala === foobar);
return new Promise(function(resolve, reject) {
在调试控制台中,我们可以看到承诺是不同的。但为什么它们必须是不同的呢
其实里面说,
[如果.then()
]返回另一个挂起的承诺对象,则返回的承诺的解决/拒绝将在处理程序返回的承诺的解决/拒绝之后进行。另外,then
返回的承诺值将与处理程序返回的承诺值相同
这表明这两个承诺是不同的(由履行处理程序返回的承诺和由.then()
返回的承诺)。(我在中找不到描述)。问题是为什么?他们不能是同一个承诺吗
第二部分说:
此外,then返回的承诺值将与处理程序返回的承诺值相同
我最初以为它的意思是“届时返回的承诺将与处理程序返回的承诺相同”,但后来才发现它的实际意思是:“那么,返回的承诺的解析值将与处理程序返回的承诺的解析值相同”。(这是正确的描述方式吗?)
在Google Chrome内部,两个承诺将显示相同的解析值123456
:,这是因为这些承诺是在不同的时间创建的:
newpromise(..).then()
返回一个立即可用的承诺(如lala
),而传递给该then
方法的回调将仅在newpromise(..)
解析时执行,即可能要晚很多时间
当然后回调最终执行时,它可以完全控制返回的内容,因此如果它决定返回一个新的承诺,那么该承诺怎么可能是前一段时间通过调用.then()
创建的承诺呢
或者,换言之,如果then
回调返回一个新的承诺,为什么JavaScript会否决该创建,并将已经存在的承诺注入其中?这是不可取的
在您的代码中,如果您在任何中检查lala
,然后
回调,您将注意到它已被定义(因为此时所有非回调代码都已完成),而对foobar
的赋值仍有待执行。它们不能相同。非常简短的回答then()返回启用方法链接的承诺,如果您告诉履行处理程序返回承诺,则将向下一个then()提供等效的承诺。也就是说,如果创建一个承诺并将其返回,.then()将访问它
下面的证明
const promise1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("resolve promise1");
}, 1000);
});
const promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve("resolve promise2");
}, 2000);
});
promise1.then(() => { return promise2 }).then(value => console.log(value))
//this will return resolve promise 2 after 2 seconds
这意味着.then()调用将使用Promise1(在本例中为promise2)的履行处理程序返回的承诺的resolve值
对于您的情况,foobar!==lala,因为在本例中lala是链中的“第一个承诺”,foobar是第四个或第五个,但是当您访问lala.then()时,您正在访问foobar承诺,但是因为它不包含任何解析值,所以您不会注意到
用一个值解析foobar并在lala中访问它。然后(res=>res…)“它们不能是相同的承诺吗?”-不,它们不能。需要先创建then()
返回的回调函数,然后再运行回调函数,该回调函数将在将来创建另一个回调函数。如果有,承诺可能会拒绝。因此,当返回foobar
时,一些机制会接受此返回值,并查看它是否为承诺,并立即调用returnedValue。然后(fn1,fn2)
,其中,fn1
是履行处理程序,它解析lala
…您可以在第2.3节的参考中找到发生的情况的规范。在该文本中,“表x
”是您的foobar
,promise
是您的lala
。您还可以了解库是如何实现该特定规范的。我已经发布了我自己的实现,很高兴你解释了OP的代码,但我很肯定OP知道这一点。重写他们的代码也很好,但我很确定OP也没有要求这样做。你在哪里试图回答他们的问题?我重新编写了代码,以便更好地解释如果其他人绊倒了会发生什么,但你没有回答问题。这就像你发布答案时的一个要求。谢谢你指出这一点。我实际上得出了一个不同的结论,似乎它们实际上是一样的。在你更新之后,这句话是错误的:“then()不返回承诺,除了…”then()
始终返回承诺。这实际上增加了混乱。