承诺链接,错误的顺序

Promises chaining, wrong order

我想了解 Javascript 中的 promises 链接。所以我写了这个 fiddle: https://jsfiddle.net/GarfieldKlon/89syq4fh/

它按预期工作。 c等待b,b等待a。

但是当我将这些行更改为:

a().then( result => console.log(result))
.then( () => {b().then( result => console.log(result))})
.then( () => {c().then( result => console.log(result))});

所以我在 b 和 c 周围添加了大括号,然后输出是 1、3、2。我不明白为什么。

当我添加 return 时,它再次起作用:

a().then( result => console.log(result))
.then( () => {return b().then( result => console.log(result))})
.then( () => {return c().then( result => console.log(result))});

但是为什么呢?如果没有花括号,你只能写一个语句,对吗?这条语句隐式 returned?

当你使用花括号时,你必须明确地 return 什么?

但是为什么在不使用 return 的情况下使用花括号会弄乱顺序?为什么在缺少 return 时它仍然会记录一些内容?

这与箭头函数有关。当您省略大括号时,return 是隐含的。所以

const f = () => 42;

相当于

const f = () => { return 42; };

此外,b().then(something).then(somenthingElse) 仍然只有一个表达式,因此可以隐式 returned。

当使用箭头语法时,你可以在很多方面解释它:

() => 'hello'

相当于

() => { return 'hello'; }

然而,当做

() => {'hello'}

与您写的相似:

.then( () => {b().then( result => console.log(result))})

那么你可以将其解释为

() => {'hello'; return;}

因此,在代码中,您的承诺处理 b().then( result => console.log(result)) 在 void return; 完成之前被调用。您根本不返回生成的 promise 对象。它会在 b 完成时被调用,无论您在做什么。

When there are no curly braces you're only allowed to write one expression which is implicitly returned? And when you use curly braces you have to explicitly return something?

.

But why does it mess up the order when using curly braces without return? And why does it still log something when the return is missing?

因为 promise then 函数依赖于 return 值进行链接。

记住then returns a new promise for the result of the callback。当该结果是另一个承诺时,它会在履行 returned 承诺之前等待该内部承诺的结果 - 您正在链接第二个 then() 调用的承诺。

如果您的回调开始 b().then(…) 但 return 开始 undefined,链中的下一步(c() 调用)不会等待 b 完成。

Promise 是表示异步操作的结果 的对象。 重要的是要记住,Promises 不仅仅是在某些异步代码完成时将回调注册到 运行 的抽象方式——它们代表该异步代码的 结果

当我们编写 .then() 调用链时,我们不会在单个 Promise 对象上注册多个回调。相反,每次调用 then() 方法 return 都是一个新的 Promise 对象。

在传递给 then() 的函数完成之前,新的 Promise 对象不会实现。满足承诺 1 的值成为 callback2() 函数的输入。回调执行一些计算并且 return 是一个值 v。当回调 return 的值时,promise 被解析为值 v

当使用本身不是 Promise 的值解析 Promise 时,它​​会立即用该值实现。

在这种情况下理解很重要,所以我改写:如果回调 return 是一个非 Promise,那么 return 值就变成了 Promise 的值,并且兑现了承诺。

如果 return 值 v 本身就是一个 Promise,那么这个 Promise 已经解决但还没有实现。

您的情况:

请允许我在此处 post 函数 a、b 和 c:

let a = function() {
    return new Promise( (resolve, reject) => {
    setTimeout(() => resolve(1), 300);
  });
}
let b = function() {
    return new Promise( (resolve, reject) => {
    setTimeout(() => resolve(2), 200);
  });
}
let c = function() {
    return new Promise( (resolve, reject) => {
    setTimeout(() => resolve(3), 100);
  });
}

和实施

a().then( result => console.log(result))
.then( () => {b().then( result => console.log(result))})
.then( () => {c().then( result => console.log(result))});

这是正在发生的事情

通过将大括号添加到箭头函数体,我们不再获得自动 return.

这个函数现在 return 是未定义的,而不是 return 一个 Promise,这意味着当前的 Promise 已经完成,这个 Promise 链中的下一个阶段将以未定义作为其输入被调用。

因此,函数 a 被调用,return 是一个承诺,一旦完成就会调用回调 1。 回调 1 returnes undefined 因此 promise1 已实现,下一个 .then() 调用回调 2。 callback2 调用 b 本身 return 是一个 Promise,但是这个 Promise 不是 return 由 callback2 编辑的。回调2 returns undefinedundefined 实现了 Promise2,生活继续 - Callback3 被调用。

此时 bc 同时 运行ning,因为 cb 快 100ms 你得到 1,3 ,2阶。

术语

如果第一个回调(then 方法的参数)被调用,我们说承诺已经实现。

如果调用第二个回调(then 方法的参数),我们说 Promise 已被拒绝。

如果一个 Promise 既没有被实现也没有被拒绝,那么它是待处理的。一旦一个承诺被履行或拒绝,我们就说它已经解决了。

如果异步代码 运行 正常(并且 Promise 已实现),那么该结果本质上就是代码的 return 值。

如果 Promise 得到满足,那么该值是一个 return 值,该值会传递给注册为 then() 的第一个参数的任何回调函数。

Promises也可以解决。很容易将此已解决状态与已完成状态或已解决状态混淆,但两者并不完全相同。

Resolved表示当前Promise的值已经赋值给另一个Promise。当前的 Promise 已与另一个 Promise 关联或“锁定”。 我们还不知道 Promise 会被履行还是被拒绝,因为它还没有确定。它的命运现在完全取决于 Promise

会发生什么