[英]Javascript loop promises synchronously with additional parameter
我有一系列的承諾,我會一個接一個地處理
function asyncInsertMagFromFile(file, resolve) {
//some asynchronous processing with file
resolve();
}
let magRequests = fs.readdirSync(storeDir).map(function(file) {
return new Promise(resolve => {
asyncInsertMagFromFile(file, resolve);
});
});
我試圖“同步”處理這些承諾(magRequests)而沒有成功。 存在關於該主題的許多問題,但我還沒有找到適合我的問題的問題。 我在這里https://stackoverflow.com/a/40329190/7531001嘗試了一些Trincot解決方案,但我不知道如何處理文件參數。
例如,這不起作用(await僅在異步函數中有效)
(async function loop() {
fs.readdirSync(storeDir).forEach(function(file) {
await new Promise(resolve =>
asyncInsertMagFromFile(file, resolve)
);
});
})();
知道我該如何解決嗎?
您可以嘗試使用array.reduce獲取先前的值(promise列表)並等待其完成,然后再調用asyncInserMagFromFile函數。
(function loop() {
fs.readdirSync(storeDir).reduce(async (previousPromise, file) => {
await previousPromise;
return new Promise(resolve =>
asyncInsertMagFromFile(file, resolve);
);
},Promise.resolve());
})();
等待僅在異步功能中有效
使用.map
而不是.forEach
,並將異步函數作為回調傳遞給它。
您可以將一些“然后是一個”鏈接在一起。
function asyncInsertMagFromFile(file) {
return new Promise((resolve, reject) => {
//some asynchronous processing with file
// call resolve when finished
resolve();
})
}
let chain = Promise.resolve();
fs.readdirSync(storeDir).forEach(function (file) {
chain = chain.then(((file) => () => asyncInsertMagFromFile(file))(file));
});
chain.then(() => {
//finished
}).catch((err) => {
//error in chain
})
另一種方法是使用注釋中提到的for語句:
function asyncInsertMagFromFile(file) {
return new Promise((resolve, reject) => {
//some asynchronous processing with file
// call resolve when finished
resolve();
})
}
(async () => {
const files = fs.readdirSync(storeDir);
for (let i = 0; i < files.length; i++) {
await asyncInsertMagFromFile(files[i]);
}
})()
這可能對您有幫助;
async function asyncInsertMagFromFile(file) {
// use await to gather results from processing or return a promise
return result;
}
function mapRequests(storeDir) {
return fs.readdirSync(storeDir).map(async function(file) {
return await asyncInsertMagFromFile(file);
});
}
mapRequests(storeDir).then((mapped) => {});
您的示例不起作用的原因是因為forEach
處理函數使用await
但未聲明為異步。
如果要順序處理並處理結果,則可以使用遞歸:
const FAILED = {};
const processImages = (files) => {
const recur=(files,result) => {
if(files.length===0){
return result;
}
return asyncInsertMagFromFile(files[0])
.catch(error=>FAILED)//always resolve, place FAILED values when rejected
.then(success=>recur(files.slice(1),result.concat(success)))
}
return recur(files,[])
}
processImages(fs.readdirSync(storeDir)).then(results=>{
console.log('failed',results.filter(r=>r===FAILED).length)
});
對於並行處理,可以使用Promise.all:
Promise.all(
fs.readdirSync(storeDir).map((file)=> asyncInsertMagFromFile(file).catch(FAILED))
).then(results=>{
console.log('failed',results.filter(r=>r===FAILED).length)
})
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.