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

我认为这是一个普遍的问题,但具体情况是:
我使用猛犸模块将docx文件转换为html 。 该模块返回一个promise
我有一个文件数组,当我使用循环来创build每个文件的承诺,我需要知道什么样的承诺返回我的结果(知道什么文件被处理)。

 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] }) } 

在写这个问题的时候,答案变得很明显(往往是这样:))。
你可以用一个自调用的函数包装承诺,并将任何相关信息存储在局部variables中。

 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 }); }) })() } 

你可以使用.map()数组方法(这很像你在函数调用方面的解决scheme,但有点干净):

 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 */ }); 

这样,你也不会用全局variables(或更高范围的variables)搞乱事情。

用另一种方式来回答你自己的答案:

在循环中创build函数并不是一个好主意,它是创build未知数量函数的好方法。 如果你使用了forEach循环,你会在它的callback函数中获得相同的封装。

 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]"