承诺的循环.如何检测哪个promise现在返回结果

Loop of promises. How to detect which promise returns the result now?

本文关键字:promise 结果 返回 检测 循环 何检测 承诺      更新时间:2023-09-26

我认为这是一个普遍的问题,但具体情况是:
我使用猛犸模块将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]
        })
}

在写这个问题的时候,答案变得显而易见了(通常是这样:))。
你可以用一个自调用的函数来包装承诺,并将相关信息存储在局部变量中。

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()数组方法(在函数调用方面与您的解决方案非常相似,但更简洁):

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

用另一个选项来回应你自己的答案:

在循环中创建函数不是一个好主意,这是一个创建未知数量函数的好方法。如果你使用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]"