承诺不在Nodejs工作的工厂

时间:2016-06-29 20:41:30

标签: javascript node.js promise

我需要在Nodejs中执行一些异步任务。在这种情况下,我需要迭代抛出JSON的al级别。出于这个原因,我需要按顺序“迭代”同步该对象。

我正在使用此代码进行测试,这是一个改编自this site

的简单示例
var fnlist = [ doFirstThing, doSecondThing, doThirdThing, lastThing];

// Promise returning functions to execute
function doFirstThing(){ return Promise.resolve(1); }  
function doSecondThing(res){ return Promise.resolve(res + 1); }  
function doThirdThing(res){ return Promise.resolve(res + 2); }  
function lastThing(res){ console.log("result:", res); }

// Execute a list of Promise return functions in series
function pseries(req,json,list) {  
  var p = Promise.resolve();
    return doFirstThing()
    .then((value) => {
        console.log('value');
        console.log(value);
        return doSecondThing(value).then((value2) => {
            console.log('value2');
            console.log(value2);
        });
    });
}

router.get('/', function(req, res, next) {
    var thisArray = json[0].array;

    for(var i = 0;i < thisArray.length; i++){
        pseries(req,json,fnlist);
    }
});

控制台输出为:

1
value
1
value
1
value2
2
value2
2
value2
2

并且仍然有效,因为我需要这种流程:

value
1
value2
2
value
1
value2
2
value
1
value2
2

我知道我需要使用 promises工厂,以便在创建它们后不立即执行它们,但现在似乎无法正常工作。我知道我不能使用.all 因为我需要使用下一个承诺中的一些数据。

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:2)

您已在for循环中启动了多个独立的承诺链(每次调用pseries()都是一个单独的承诺链)。因此,您无法控制单独的承诺链的排序。如果你想控制一个链与另一个链,那么你将不得不链接它们(例如将它们链接在一起),所以排序是明确的而不是偶然的。

您看到的输出并不令人惊讶,因为您的for循环所做的第一件事就是注册一堆.then()个处理程序。因为已经为这些承诺解决了承诺,所以.then()循环完成后,for处理程序都排队等待运行.then()处理程序始终排队异步运行) 即可。 for循环完成,然后第一批.then()个处理程序全部运行。运行它们的过程会安排另外三个.then()个处理程序。然后排队等待它们在第一批.then()处理程序完成时运行。虽然我解释了为什么你得到你看到的订单的可能逻辑,但这不能保证。这些都是异步操作,你唯一知道的是他们将来会完成一些不确定的时间。如果你想要明确的订单,你必须通过显式同步你的承诺来强迫它。

您可以使用array.reduce()相当常见的设计模式,按照已知顺序对数组进行迭代排序:

router.get('/', function(req, res, next) {
    var thisArray = json[0].array;

    thisArray.reduce(function(p, item) {
        return p.then(function() {
            return pseries(req,json,fnlist);
        });
    }, Promise.resolve()).then(function(result) {
        // all done here
    }, function(err) {
        // error here
    });
});

答案 1 :(得分:0)

尝试使用foreach链接所有承诺:

var sequence = Promise.resolve();

// Loop through our chapter urls
story.chapterUrls.forEach(function(chapterUrl) {
  // Add these actions to the end of the sequence
  sequence = sequence.then(function() {
    return getJSON(chapterUrl);
  }).then(function(chapter) {
    addHtmlToPage(chapter.html);
  });
});

对于更复杂的组合,请查看此页面: http://www.html5rocks.com/en/tutorials/es6/promises/#toc-parallelism-sequencing