javascript - 深承诺.all
问题描述
我有一个以保存文件列表结尾的承诺链。我想等到所有文件都保存或失败,然后继续我的链。问题是,当我Promise.all
在具有自己的子链的 Promise 列表上使用时then
,Promise.all
开始时的then
s 在Promise.all
. 请参阅下面的注释示例。
const fs = require('fs');
const util = require('util');
// Make a promise out of the file write function
const promiseWriteFile = (file, data, options) => {
return util.promisify(fs.writeFile).call(fs, file, data, options);
};
...
console.log('Received files');
console.group();
// Start long promise chain
somePromise(...)
.then((result) => {
console.log('validating blah blah');
})
.then((result) => {
...
})
.then((result) => {
// Now I need to save the files to the disk
let path = './uploaded_files/';
// Here I want to resolve all the file save promises, or find one that fails
return Promise.all(
request.files.map((file) => {
let filename = path + Date.now() + '_' + file.originalname;
// Purposely change `path` so that the next file write will fail
path = './garbage/';
console.log('Trying to save file:', filename);
return promiseWriteFile(filename, file.buffer, 'binary')
.then(() => {
console.log('Saving file:', filename);
})
.catch((error) => {
console.log('Could not save file:', filename);
throw error;
});
}),
);
})
.then(() => { // <======= I don't want this to happen until the promises in the `Promise.all` above have fully, DEEPLY resolved
// set success message
message = 'Part successfully created.';
console.groupEnd();
console.log('Part created successfully.');
})
.catch((exception) => {
message = exception.message;
console.groupEnd();
console.log('Part invalid.');
});
输出如下所示:
Received files
validating blah blah
Trying to save file: ./uploaded_files/A.txt
Trying to save file: ./garbage/B.txt
Part invalid.
Could not save file: ./garbage/B.txt
Saving file: ./uploaded_files/A.txt
如您所见,打印“无法保存文件”和“保存文件”的行在大承诺链的 then/catch 之后执行。您可以判断,因为console.groupEnd()
首先被调用,然后有进一步的输出。
在所有子承诺完成之前,如何确保大承诺链上的 then/catch 不会发生?
解决方案
你在你的 catch 块中抛出错误map
.catch((error) => {
console.log('Could not save file:', filename);
throw error;
});
这会破坏你Promise.all()
并导致它在完成所有承诺之前陷入困境。相反,您应该只是转发该错误而不是使错误链崩溃。您需要重新考虑如何确认所有写入以及以下步骤。
稍后处理退货的示例:
.then((result) => {
let path = './uploaded_files/';
return Promise.all(
request.files.map((file) => {
let filename = path + Date.now() + '_' + file.originalname;
path = './garbage/';
console.log('Trying to save file:', filename);
return promiseWriteFile(filename, file.buffer, 'binary')
.then(() => {
return { filename };
})
.catch((error) => {
return { error, filename };
});
}),
);
})
.then((results) => {
const successes = results.filter(({ error }) => !error);
const failures = results.filter(({ error }) => error);
// process them here
})
现在您可以按照您的意愿处理它们,并且每个对象在返回中都有一个文件名,让您可以识别它们,删除它们,无论您想要什么。
推荐阅读
- r - 纵向数据集中的折叠行
- java - Azure 应用服务上的 Tomcat Web-App 404-0 错误
- arrays - TensorFlow 中这个 Numpy 代码的等价物是什么?
- c# - ExecuteReader 抛出 ORA-01840 但来自 sqlDeveloper 运行良好
- couchdb - CouchDB芒果忽略索引排序顺序
- corda - 更新状态的子关系行的最佳实践是什么?
- python-3.x - 如何让我的程序在循环的每次迭代中选择一个新的随机数?- 魔术 8 球
- android - 更新后“所有 com.android.support 库必须使用完全相同的版本规范”
- javascript - 按父 ID 递归搜索后代
- solr - 从 C# 访问 Solr 8