Promise.all() 解析,但它不应该(node.js)

Promise.all() resolving, but it shouldn't (node.js)

本文关键字:不应该 node js all 解析 Promise      更新时间:2023-09-26

我现在正在node.js中尝试这样的事情:

var exec = require('child_process').exec
var write = require('fs-writefile-promise')
function run() {
    var myArray = [];   
    var execs = [];
    for (var i = 1; i <= 7; i++) {
        (function(cntr) {
            write('file-' + i + '.txt', someString)
            .then(function (filename) {
                execs.push(new Promise(function(resolve, reject) {
                    exec('cat ' + 'file-' + cntr + '.cnf', function(error, stdout, stderr) {
                        console.log(cntr + ' ' + stdout);
                        if (stdout.search(/'bsomeString'b/) > -1) {
                            myArray.push(cntr);
                            resolve();
                        } 
                        else {
                            resolve();
                        }   
                    })
                }))
            })
            .catch(function (err) {
                console.error(err);
            });
        })(i);
    }
    return Promise.all(execs).then(function() {
        return new Promise(function(resolve) {
            resolve(myArray);
        }) 
    })
}
run().then(function(result) {
    console.log(result);
});

如您所见,我正在创建多个exec()运行的承诺,每个承诺在exec()完成后都会解决。然后,我正在等待每个承诺在Promise.all(execs)中解决,myArray作为承诺返回。然而,当我在最后执行我的 run() 函数时,它返回了一个空数组。我想这与Promise.all()有关,因为即使execs中的某些承诺尚未解决,它也会解决,但我不确定,这就是为什么我真的需要一些帮助。有谁知道我在代码中哪里犯了错误?

提前非常感谢!

#EDIT 1

var exec = require('child_process').exec
var write = require('fs-writefile-promise')
function run() {
    var myArray = [];   
    var execs = [];
    for (var i = 1; i <= 7; i++) {
        (function(cntr) {
            return new Promise(function(resolve, reject) {
                fs.writeFile('file-' + i + '.txt', someString, (err) => {
                    if (err) {
                        reject();
                    }
                    else {
                        resolve();
                    }
                });
            })
            .then(function (filename) {
                execs.push(new Promise(function(resolve, reject) {
                    exec('cat ' + 'file-' + cntr + '.cnf', function(error, stdout, stderr) {
                        console.log(cntr + ' ' + stdout);
                        if (stdout.search(/'bsomeString'b/) > -1) {
                            myArray.push(cntr);
                            resolve();
                        } 
                        else {
                            resolve();
                        }   
                    })
                }))
            })
            .catch(function (err) {
                console.error(err);
            });
        })(i);
    }
    return Promise.all(execs).then(function() {
        return new Promise(function(resolve) {
            resolve(myArray);
        }) 
    })
}
run().then(function(result) {
    console.log(result);
});

您的两次尝试都存在许多问题。 第一次尝试的问题在于,您在异步操作后填充execs数组,因此当您实际将数组传递给Promise.all()时,它没有任何内容,因此Promise.all()没有什么可等待的。

此外,您

不仅使用已经创建的承诺,因此您最终做出的承诺比需要的要多。

一般来说,最好在主逻辑之外"承诺"你的异步操作一次,然后让你所有的逻辑都由承诺驱动,而不是将承诺与普通回调混合和匹配。 以下是尝试解决这些问题的版本:

var exec = require('child_process').exec
var write = require('fs-writefile-promise')
// make promisified version of exec
function execP(file, options) {
    return new Promise(function(resolve, reject) {
        exec(file, options, function(err, stdout, stderr) {
            if (err) return resolve(err);
            resolve({stdout: stdout, stderr: stderr});
        });
    });
}
function run() {
    var promises = [];
    for (var i = 1; i <= 7; i++) {
        promises.push(write('file-' + i + '.txt', someString).then(function(filename) {
            return execP(filename);
        }));
    }
    return Promise.all(promises).then(function(results) {
        // results is an array of {stdout: xxx, stderr: yyy} objects
        // process those results into a new array of just indexes
        var final = [];
        results.forEach(function(data, index) {
            if (data.stdout.search(/'bsomeString'b/) > -1) {
                final.push(index);
            }
        });
        return final;
    });
}
run().then(function(results) {
    // array of indexes that contained the desired search string
}, function(err) {
    // process error here
});

注意:这将并行运行所有 exec 操作,这就是原始代码所做的。 如果你想按顺序运行它们,也可以这样做,但需要一些调整。

由于write是异步的,因此此阶段的程序将传递回主线程,并且直接传递到您的承诺.all,并在加载execs之前返回该内容。

我建议您创建一个函数,该函数返回文件保存后跟exec的承诺。