我有一个承诺链,以保存文件列表结束。我想等到所有文件保存或失败,然后继续我的链子。问题是,当我在有自己的子链的承诺列表上使用Promise.all时,Promise.all上的thens开始解决,而then则在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因此,正如您所看到的,打印“无法保存文件”和“保存文件”的行在大承诺链的“那时/捕获”之后执行。您可以判断,因为console.groupEnd()首先被调用,然后才有进一步的输出。
如何确保在所有的子承诺完成之前,大承诺链上的捕获不会发生?
发布于 2020-06-26 18:22:25
您正在map上的catch块中抛出错误
.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
})现在您可以以您想要的方式处理它们,并且每个对象在返回中都有一个文件名,允许您识别它们,删除它们,不管您想要什么。
发布于 2020-06-26 18:20:37
当您在.catch上使用promise.all时,它将为您添加的每个子承诺添加捕获。没有"catchFinally“方法。
要阻止其他承诺的发生,请看下面的示例:
Promise.config({ cancellation: true }); // <-- enables this non-standard feature
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'resolve1');
}).then(a => { console.log('then1'); return a; });
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 2000, 'reject2');
}).then(a => { console.log('then2'); return a; });
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 3000, 'resolve3');
}).then(a => { console.log('then3'); return a; });
const promises = [promise1, promise2, promise3];
Promise.all(promises)
.then(values => {
console.log('then', values);
})
.catch(err => {
console.log('catch', err);
promises.forEach(p => p.cancel()); // <--- Does not work with standard promises
});请注意,即使promise3被取消,它的setTimeout回调仍将被调用。但它不会触发当时的回调或捕捉回调。就好像这个承诺永远不会达成决议.永远不会。
https://stackoverflow.com/questions/62600602
复制相似问题