[英]Loop of promises. How to detect which promise returns the result now?
I think it's a common question, but for concreteness the situation is: 我认为这是一个常见的问题,但具体情况是:
I use the mammoth module to convert docx
files to html
. 我使用庞大的模块将
docx
文件转换为html
。 The module returns a promise
. 该模块返回一个
promise
。
I have an array of files and when I use a loop to create a promise for every file I need to know what promise returns me a result (to know what file was processed). 我有一个文件数组,当我使用循环为每个文件创建一个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]
})
}
While writing the question, the answer became obvious (as is often the case :) ). 在撰写问题时,答案变得明显(通常情况:)。
You can wrap the promise with a self invoked function and store any related info in local variable. 您可以使用自调用函数包装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
});
})
})()
}
You can use .map() array method (which is much like your solution in terms of function calls, but a bit cleaner): 您可以使用.map()数组方法(这与函数调用方面的解决方案非常类似,但更清晰一点):
filesPaths.map(function(fileName, i){
mammoth.convertToHtml({path: fileName})
.then(/* ... */)
;
});
// Here filesHtml is empty and you don't know when will be filled!!
...which is dirty (see the comment at the end). ......这很脏(见最后的评论)。
Or you can simply use Promise.all() to collect the results: 或者你可以简单地使用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 */
});
This way, you also aren't messing things with global (or higher scope) variables. 这样,您也不会弄乱全局(或更高范围)变量。
To respond to your own answer with an alternative: 用另一种方式回答你自己的答案:
Creating functions in loops is not a great idea, it's a pretty good way to an unknown number of functions created. 在循环中创建函数不是一个好主意,它是创建未知数量的函数的一种非常好的方法。 If you used a forEach loop you would get the same encapsulation in its callback function.
如果使用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]"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.