bluebird如何知道在这个链中继续下一个`then`?

时间:2016-12-01 23:12:44

标签: javascript node.js promise bluebird chaining

宣传fs-extra,我明白我可以使用then来访问文件。我猜测那里有一些机制,在它获得文件后,它知道移动到then链中的下一个链接。但是,下一个then我只是放了一个简单的for循环。下一个只是在控制台上打印一行。我希望返回一些Promise对象,让它向下移动链。沿着这条链走下去需要什么?例如,如果我将setTimeout放入一秒钟,则链继续并按顺序打印。

var Promise = require('bluebird')
  , fs = Promise.promisifyAll(require('fs-extra'))

fs.readdirAsync(dir)
    .bind(this)
    .then((files) => {
        this.files = files;
    })
    .then(() => {
        var num = 10000
        this.files.forEach((file, index, array) => {
            for(i = 0; i < num; i++){
                console.log(num*i);
            }
        });
    })
    .then(() => {
        console.log('middle of it');
    })
    .then(() => {
        console.log('done with it');
    })
    .catch((err) => {
        console.log(err);
    });

1 个答案:

答案 0 :(得分:3)

每次调用.then()都会返回一个具有自己的.then()处理程序的新承诺。该承诺自动链接到之前的承诺,因此当前一个承诺完全由它自己的.then()处理程序完成时,.then()处理程序没有返回承诺或者它是当它返回的那个承诺被解决时,它可以触发链中的下一个承诺来解决,导致它重复它的.then()处理程序的循环。

关键是p.then()返回一个新的承诺,当p.then()完成后,它将自行解决,这样它就可以触发链p.then().then()中的下一步,依此类推。

请记住,.then()处理程序可以执行以下四种操作之一:

  1. 不返回任何内容(与返回undefined相同)。
  2. 返回值
  3. 回复承诺
  4. 抛出异常
  5. 对于前两个(返回值),这只表示.then()处理程序已完成,然后可以立即触发链中的下一个处理程序。

    在返回承诺时,该承诺本身与.then()处理程序挂钩,因此可以对其进行监控。如果/当它结算时,链继续。如果/当它拒绝时,链被拒绝。返回的承诺可能已经被解决或拒绝,或者将来可能被解决或拒绝,行为没有任何有意义的差异。如果从未解决或拒绝退回的承诺,则承诺链将停止运行,并且在解决或拒绝之前不会继续(与任何承诺相同)。

    如果.then()处理程序抛出异常,则会被.then()包装器捕获,并自动转换为被拒绝的承诺,异常作为拒绝原因。

      

    例如,如果我输入setTimeout一秒钟,那么链   继续并打印失序。

    您无法有效地使用setTimeout()来延迟承诺链。相反,您需要从.then()处理程序返回一个在一些超时时间后解析的promise。蓝鸟有.delay(x)为你做这件事。

    或者,如果不使用Bluebird,您可以自己编码:

    function delay(t) {
        return new Promise(function(resolve) {
            setTimeout(resolve, t);
        });
    }
    
    fn().then(function() {
        // delay promise chain by 1000ms
        return delay(1000);
    }).then(function() {
        // promise chain continues here
    });
    

    或者,有了Bluebird的承诺,它就像:

    一样简单
     fn().delay(1000).then(function() {
         delayed promise chain continues here
     });