首页 > 解决方案 > 深承诺.all

问题描述

我有一个以保存文件列表结尾的承诺链。我想等到所有文件都保存或失败,然后继续我的链。问题是,当我Promise.all在具有自己的子链的 Promise 列表上使用时thenPromise.all开始时的thens 在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 不会发生?

标签: javascriptpromise

解决方案


你在你的 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
    })

现在您可以按照您的意愿处理它们,并且每个对象在返回中都有一个文件名,让您可以识别它们,删除它们,无论您想要什么。


推荐阅读