是可以链接异步 - Promises?

时间:2018-05-28 19:24:34

标签: javascript node.js promise

thenable如何链接异步?看起来从前一个promise返回的Promise.then阻塞(意图本身将按照下面给出的示例阻止)链中的下一个Promise.then。我是Node.js中promises的新手。谁能帮助我更好地了解thenable链接是如何异步的?
从给定的示例中,为什么我们不使用同步函数而不是使用thenable链?

new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

  alert(result); // 1
  return result * 2;

}).then(function(result) { // (***)

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

3 个答案:

答案 0 :(得分:2)

then链是异步的,因为承诺链之后的代码将在不等待承诺达到其解析状态的情况下执行。

function sleep (ms) {
    return new Promise(resolve, setTimeout(resolve, ms));
}

// counts to 3 in 3 seconds, thanks to asynchronicity
sleep(3000).then(() => console.log('3'));
sleep(2000).then(() => console.log('2'));
sleep(1000).then(() => console.log('1'));

给定promise的then方法提供了附加任何函数的方法 应等待其返回值(*)。 因此,承诺链表示同步的指令序列" 但它与程序的其余部分是异步的。

function add (i) {
    return sleep(1000)
        .then(() => { console.log(i+1); return i+1 });
}

// counts to 3 in 3 seconds, thanks to synchronicity along the chain
Promise.resolve(0).then(add).then(add).then(add);

当然,如果只需处理线性链,那么引入异步性就完全没用了。 仅在创建并行链时出现相关性。相反,请使用这个简单的同步shell脚本:

// counts *down* in 6 seconds
sleep 3; echo 3;
sleep 2; echo 2;
sleep 1; echo 1;

观察睡眠通常表示在网络上等待一些不同的资源,以清楚地了解异步性的好处。

与此同时,在没有方便的方法来线性化任务并让一些代码彼此等待的情况下,异步性是不可能处理的。 承诺是实现这一目标的一种便捷方式,在过去的"厄运的回调金字塔"以及ECMA 2017异步/等待关键字,例如see here

(*)小心总是在中间函数中返回一些东西, 否则链条的其余部分可能会停止等待。

答案 1 :(得分:0)

不,它没有阻止then()来电。在创建承诺后立即发生所有then()次调用,并且代码继续同步运行。

只有then 回调才会异步延迟,直到承诺得到解决。并且每个then()调用都会为回调结果返回一个新的承诺,这样您就可以将它们链接在一起,并且每个回调都将在另一个之后被调用。

但是没有阻止:

console.log("creating the first promise");
var promise = new Promise(function(resolve, reject) {
    console.log("starting the timeout")
    setTimeout(() => {
        console.log("resolving the first promise");
        resolve(1);
    }, 1000);
});
console.log("installing the callback");
var nextPromise = promise.then(function(result) {
    console.log("receiving the result", result);
    return result * 2;
});
console.log("continuing synchronously after the then() call");

// and so on with
// nextPromise.then(nextResult => console.log("receiving second result", result));

答案 2 :(得分:0)

让我回答为什么提问。如果你考虑你的代码那么它并不重要,你可以做到没有承诺就好了。像这样。

setTimeout(() => {
  let result = 1;
  alert(result);
  result *= 2;
  alert(result);
  result *= 2;
  alert(result);
  result *= 2;
}, 1000);

但那是因为来自setTimeout的aparat,代码是同步的。但想象一下,如果你想在没有承诺的情况下链接异步函数。你仍然可以这样做,但它会导致相当复杂,难以阅读的代码(回调地狱)。

让我们看看你的代码在这种情况下会是什么样子。

setTimeout(function() {
  let result = 1;
  alert(result);

  setTimeout((function(result) {
    result *= 2;
    alert(result);

    setTimeout((function(result) {
      result *= 2;
      alert(result);
    }).bind(null, result), 0);
  }).bind(null, result), 0);
}, 1000);

它仍然是一样的,但它看起来比使用promises的代码更糟糕。 (想象一下,如果你想连接更多的话会是怎样的,比方说10,这样的功能)