为什么在完成Promise.all()之前先执行Promise.then()?

时间:2018-10-10 14:56:36

标签: javascript node.js express es6-promise

我想在创建文件列表之后执行代码,但是之前正在执行该代码。

检查以下psudo代码中的注释,以更好地理解。

伪代码:

var fs = require('fs');

Promise.all([
    fs.writeFile(...),
    list.forEach(element => {      // I think the problem is here
        fs.writeFile(...);         // The files content is big
        console.log(element.name); // This is printing after then() method
    })
]).then((v) => {
    console.log(v); // This is printing before the files being created
});

我希望已经很好地解释了我的问题。预先感谢。

4 个答案:

答案 0 :(得分:1)

如果您传递给它的所有承诺都得到解决,则Promise返回的Promise.all()将得到解决。

请注意,fs.writeFile不会返回promise,但是您可以通过导入使用fs Promises API

var fs = require('fs').promises

相反(但要注意,这是实验性的。)

但是您仍然只能通过一个承诺:fs.writeFile(...)

list.forEach(...)不会返回Promise,因此Promise.all()等不及了。

尝试类似(伪代码)的方法:

Promise.all([
    fs.writeFile(...),
    ...list.map(element => { // convert list to an array of promises
        console.log(element.name); 
        return fs.writeFile(...);   
    })
]).then((v) => {
    console.log(v);
});

答案 1 :(得分:1)

Promise.all需要一系列的Promise。如果您在数组中传递的不是Promise,它将立即得到解决。

fs.writeFile不会返回Promise,它是一个nodeJS函数,期望以(err, result)形式进行回调。您可以使用util.promisify使其成为返回Promise的函数。

您的第二个参数甚至更不是一个承诺,因为它只是一个forEach。可以通过返回Promise.all中的另一个list.map(...)来解决,其中映射函数返回一个Promise。

答案 2 :(得分:1)

使用bluebird承诺,我们可以获得承诺回报。

const writeFile = require("bluebird").promisify(fs.writeFile);

Promise.all([
    fs.writeFile(...),
    ...list.map(element => {
        console.log(element.name); 
        return writeFile(...);   
    })
]).then((v) => {
    console.log(v);
});

答案 3 :(得分:1)

仅供参考,我正在演示一种使承诺的异步函数实现的方法。

const fs = require('fs');
const writeFile = function(file, data, options){
    new Promise((resolve,reject) => {
        fs.writeFile(file, data, options, (err) => {
            if(err){
                return reject(err);
            }
            return resolve();
        });
    });
}

现在您可以按以下方式使用此writeFile函数

writeFile(filePath, data, options)
    .then(() => {
        // operation successful, handle your logic here
    }).catch((e) => {
        // something is wrong, handle the error here.
    });

一旦您知道了promise是如何工作的,那么转换异步函数就非常简单。

要在Promise.all中使用此功能,我们可以执行以下操作-

Promise.all([
    writeFile(...), // pass your arguments here
    ...list.map(element => { // convert list to an array of promises
        // use the function to create a promise as following, 
        // make sure to match the arguments as per your need 

        return writeFile(element.filePath, element.data, element.options);
    })
]).then((v) => {
    console.log(v);
});

为总结这里发生的事情,我们正在创建一个promise数组并将其传递给Promise.all函数。我们正在使用基本函数writeFile创建一个Promise数组,该函数返回一个Promise并在写入文件后解析。我们正在使用es6扩展运算符...来扩展list对象的元素。

我希望这将来对某人有帮助。