承诺循环。如何检测哪个承诺现在返回结果?

时间:2016-10-26 12:06:02

标签: javascript node.js promise

我认为这是一个常见的问题,但具体情况是:
我使用mammoth模块将docx个文件转换为html。该模块返回promise 我有一个文件数组,当我使用循环为每个文件创建一个promise时,我需要知道什么promise会返回一个结果(知道处理了哪个文件)。

for(var i=0;i<filesPaths.length;i++){
    mammoth.convertToHtml( {path: filesPaths[i]} )
        .then(function(result){
            filesHtml.push(result.value);
            //here I need to know the value of filesPaths[i]
        })
}

3 个答案:

答案 0 :(得分:2)

在撰写问题时,答案变得明显(通常情况:): 您可以使用自调用函数包装promise,并将任何相关信息存储在局部变量中。

for(var i=0;i<filesPaths.length;i++){
   (function(){
     var fileName = filesPaths[i]; //or any other information related to promise
     mammoth.convertToHtml( {path: filesPaths[i]} )
        .then(function(result){
            filesHtml.push({
                text:result.value,
                fileName:fileName
                         });

        })
    })()
}

答案 1 :(得分:1)

您可以使用.map()数组方法(这与函数调用方面的解决方案非常相似,但更清晰一点):

filesPaths.map(function(fileName, i){
  mammoth.convertToHtml({path: fileName})
    .then(/* ... */)
  ;
});
// Here filesHtml is empty and you don't know when will be filled!!

......这很脏(见最后的评论)。

或者你可以简单地使用Promise.all()来收集结果:

var P = Promise.all(
  filesPaths.map(function(fileName){
    return mammoth.convertToHtml({path: fileName});
  })
).then(function(resultArr){
  return Promise.all(resultArr.map(function(result, i){
    return {
      text: text.value,
      fileName: filesPaths[i],
    };
  }));
}).then(function(filesHtml){
  /* Here you know filesHtml is fully filled */
});

P.then(function(filesHtml){
  /* ...and here too */
});

这样,你也不会弄乱全局(或更高范围)变量。

答案 2 :(得分:0)

用另一种选择回答你自己的答案:

在循环中创建函数不是一个好主意,它是创建未知数量的函数的一种非常好的方法。如果你使用了forEach循环,你将在其回调函数中获得相同的封装。

var arr = ['a', 'b', 'c'];

function prom(thing) {
    return Promise.resolve(thing);
}

for (var i = 0; i < arr.length; i++) {
    prom(arr[i]).then(function(val){ 
        console.log(`for: got val ${val} with arr[${i}]`);
    });
}   
// Logs:
// "for: got val a with arr[3]"
// "for: got val b with arr[3]"
// "for: got val c with arr[3]"

arr.forEach(function(val, index) {
    prom(val).then(function(val){ 
        console.log(`forEach: got val ${val} with arr[${index}]`);
    });      
});
// Logs:
// "forEach: got val a with arr[0]"
// "forEach: got val b with arr[1]"
// "forEach: got val c with arr[2]"