为什么我的代码按此顺序打印? (JavaScript承诺)

时间:2019-07-20 03:27:41

标签: javascript node.js

我试图理解Promise /异步编程,但我不理解为什么这段代码显示“ 1 2 0”而不是“ 2 1 0”。从第三段代码开始:f1不应仅在f2将“ 2”记录到控制台后才触发?

const f1 = new Promise((resolve,reject)=>{
  setTimeout(()=>{
      resolve(console.log(1));
  }, 1000)
})

const f2 = new Promise((resolve, reject)=>{
  setTimeout(()=>{
    resolve(console.log(2))
  }, 1500)
})

f2.then(
  f1.then(()=>{
    setTimeout(()=>{
        console.log(0);
    }, 500)}
));

我正在尝试一个程序,该程序需要几个(如6ish)异步函数以非常特定的顺序触发,即f2()必须等到f1()完全接收到来自执行请求的数据后,我我实际上不确定该怎么做...

1 个答案:

答案 0 :(得分:0)

您正在并行运行f1和f2操作,一个接一个地启动它们。两者都开始,然后它们同时在飞行中。

然后,您需要将函数引用传递给.then(),以便该函数可以在将来某个时间(当主机Promise解析时)调用Promise基础结构。相反,您是向.then()传递了一个诺言,这没有任何用处。

如果您将代码更改为此:

const f1 = new Promise((resolve,reject)=>{
  setTimeout(()=>{
      resolve(console.log(1));
  }, 1000)
})

const f2 = new Promise((resolve, reject)=>{
  setTimeout(()=>{
    resolve(console.log(2))
  }, 1500)
})

f2.then(() => {
  f1.then(()=> {
    setTimeout(()=>{
        console.log(0);
    }, 500)}
  });
});

然后,您将立即启动f1和f2计时器。然后,只有在f2和f1都完成之后,您才启动第三个计时器,并且应该获得输出1 2 01之所以排在第一位,是因为它的计时器比2短,它们都是并行运行的。 0之所以排在最后,是因为直到12都完成后,计时器才开始计时。


如果要链接它们以获得2 1 0,则不必同时启动21。使f1和f2成为函数,而不是诺言,以便您可以在调用它们时进行排序。

    function delay(t) {
        return new Promise(resolve => {
            setTimeout(resolve, t);
        });
    }

    function f1() { 
      return delay(1000).then(() => {
          console.log(1);
      })
    }
    
    function f2() { 
      return delay(1500).then(() => {
          console.log(2);
      })
    }

    function f3() {
      return delay(1500).then(() => {
          console.log(0);
      })
    }

    // chain them together 
    f2().then(f1).then(f3).then(() => {
        console.log("done");
    });

这种.then()链接基本上是这样说的:

  • 执行f2()
  • .then()返回的诺言上注册.f2()处理程序,以便当该诺言得到解决时,它将(且仅在此之后)调用f1。
  • 根据f2().then()返回的新承诺,在其上注册.then()处理程序,以便在f1完成后将调用f3。
  • 根据f2().then().then()返回的新承诺,注册一个在f3完成后将被调用的回调。