【问题标题】:when does Promise.resolve() trigger then() method? [duplicate]Promise.resolve() 什么时候触发 then() 方法? [复制]
【发布时间】:2021-08-14 13:26:01
【问题描述】:

我正在学习 js 中的 Promise,对此我有一些疑问,代码如下:

Promise.resolve().then(() => {
  console.log(0);
  return Promise.resolve(4);
}).then((res) => {
  console.log(res)
})

Promise.resolve().then(() => {
  console.log(1);
}).then(() => {
  console.log(2);
}).then(() => {
  console.log(3);
}).then(() => {
  console.log(5);
}).then(() => {
  console.log(6);
})

输出与我的预期相差甚远,我认为它会是 0 1 4 2 3 5 6,因为我在 MDN 上看到了这个

Promise.resolve() 方法返回一个用给定值解析的 Promise 对象

所以 log() 方法不应该在数字 1 后面触发吗?

我做错了什么?

【问题讨论】:

  • 此外,即使我们将Promise.resolve(4) 替换为Promise.resolve(4).then(res=>res),它的工作原理也是一样的。但是,then 链接在相同的位置上会推动4 在输出中更进一步。
  • 如果我们将Promise.resolve(4) 替换为Promise.resolve(4).then(res => console.log(res));,那么订单将是0 1 4 ....

标签: javascript es6-promise


【解决方案1】:

Promise 不是直接处理的,而是基于队列的。如果 promise 完成,则在下一个处理周期中处理回调。

如果我们用更详细的代码替换您的代码,我们会得到:

const a = Promise.resolve('a');

const b = a.then(() => {
  console.log('b');
  const c = Promise.resolve('c');
  return c;
});

const ca = b.then((res) => {
  console.log('ca', res)
})

const u = Promise.resolve('u');

const v = u.then(() => {
  console.log('v');
});

const w = v.then(() => {
  console.log('w');
});

const x = w.then(() => {
  console.log('x');
});

const y = x.then(() => {
  console.log('y');
});

const z = y.then(() => {
  console.log('z');
});

第一次传递代码是从上到下运行的,并没有发生很多事情。两个 Promise 已解决(au)被放入队列中,并且没有打印任何内容。当它们在下一个周期中被处理时,它们会将bv 排队。

每当处理下一个周期时,b 首先启动,记录"b" 并将c 排队。之后,处理v,记录"v" 并排队w

现在,c 已完成,并将下一个 ca 排队(间接,因为在承诺中返回承诺),但不打印任何内容。以此类推。

一路向下,它看起来像这样:

// Main tick
// - queue a
// - queue u

// Queue tick
// - resolve a, queues b
// - (log nothing)
// - resolve u, queues v
// - (log nothing)

// Queue tick
// - resolve b, queues c
// - log "b"
// - resolve v, queues w
// - log "v"

// Queue tick
// - resolve c, doesnt log, queues the next (ca)
// - resolve w, queues x
// - log "w"

// Queue tick
// - resolve x, queues y
// - log "x"
// - resolve ca, queues nothing
// - log "ca, c"

// Queue tick
// - resolve y, queues z
// - log "y"

// Queue tick
// - resolve z
// - log "z"

我不知道这是否是实际要求,因此如果实现(浏览器)决定直接处理承诺,则顺序可能会改变。不过我认为这不太可能,因为它不鼓励公平,并且如果一个承诺被永远链接起来,这个承诺将获得分配给它的所有资源。

我认为一般建议是不要依赖于完成承诺的顺序。将a.then(b) 想象为,b 仅在a 完成后发生,而不是更早,仅此而已。

如果您需要多个 Promise 相互依赖,请使用 Promise.all()Promise.any()

【讨论】:

  • 请强调一般建议不要依赖于promise的完成顺序
  • 这里有几个疑问。我不明白我们为什么要排队等待承诺。排队发生在回调不是吗?同样在第三个队列滴答声中,CAx 之前排队,但在下一个滴答声中,您将在CA 之前解析x
  • @LakshyaThakur 是的,排队是为了承诺工作(解决 thenables,并在已确定的承诺上执行 then 处理程序)而不是为了“承诺”本身
猜你喜欢
  • 2010-11-18
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多