Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript/NodeJS:在forEach循环中推送值后数组为空_Javascript_Node.js_Mongoose_Npm_Foreach - Fatal编程技术网

Javascript/NodeJS:在forEach循环中推送值后数组为空

Javascript/NodeJS:在forEach循环中推送值后数组为空,javascript,node.js,mongoose,npm,foreach,Javascript,Node.js,Mongoose,Npm,Foreach,我有点小问题。代码如下: 情景A: var foundRiders = []; riders.forEach(function(rider){ Rider.findOne({_id: rider}, function(err, foundRider){ if(err){ console.log("program tried to look up rid

我有点小问题。代码如下:

情景A:

var foundRiders = [];

            riders.forEach(function(rider){
                Rider.findOne({_id: rider}, function(err, foundRider){
                    if(err){
                        console.log("program tried to look up rider for the forEach loop finalizing the results, but could not find");
                    } else {
                        foundRiders.push(foundRider);
                        console.log(foundRiders);
                    }
                });
            });
情况B

var foundRiders = [];

            riders.forEach(function(rider){
                Rider.findOne({_id: rider}, function(err, foundRider){ 
                    if(err){
                        console.log("program tried to look up rider for the forEach loop finalizing the results, but could not find");
                    } else {
                        foundRiders.push(foundRider);
                    }
                });
            });
            console.log(foundRiders);
所以在一个控制台日志中,我得到foundRiders是一个充满对象的数组。在情况B中,当我将console.log放在循环外时,我的roundRiders数组完全为空


为什么呢?

正如其他人所说,您的数据库代码是异步的。这意味着您的循环中的回调将在稍后的某个时间调用,而这是在您的循环已经完成很久之后。为异步循环编程有多种方法。在您的情况下,最好转到数据库的promise接口,然后开始使用promises来协调多个数据库调用。您可以这样做:

Promise.all(riders.map(rider => {
    return Rider.findOne({_id: rider}).exec();
})).then(foundRiders => {
    // all found riders here
}).catch(err => {
    // error here
});
这将使用mongoose数据库的
.exec()
接口运行查询并返回承诺。然后,
riders.map()构建并返回这些承诺的数组。然后,
Promise.all()
监视数组中的所有承诺,并在它们全部完成时调用
.Then()
,或者在出现错误时调用
.catch()


如果要忽略数据库中未找到的任何附加程序,而不是因错误而中止,则可以执行以下操作:

Promise.all(riders.map(rider => {
    return Rider.findOne({_id: rider}).exec().catch(err => {
        // convert error to null result in resolved array
        return null;
    });
})).then(foundRiders => {
    foundRiders = foundRiders.filter(rider => rider !== null);
    console.log(founderRiders);
}).catch(err => {
    // handle error here
});

为了帮助说明这里发生了什么,这是一种更老式的监视所有数据库回调完成的方式(使用手动计数器):

维护计数器以跟踪多个异步请求是
Promise.all()
内置的功能


上面的代码假设您希望并行化代码并一起运行查询以节省时间。如果您想序列化查询,那么您可以在ES6中使用
wait
for
循环,使循环对每个结果“wait”(这可能会减慢速度)。以下是您将如何做到这一点:

async function lookForRiders(riders) {
    let foundRiders = [];
    for (let rider of riders) {
        try {
            let found = await Rider.findOne({_id: rider}).exec();
            foundRiders.push(found);
        } catch(e) {
            console.log(`did not find rider ${rider} in database`);
        }
    }
    console.log(foundRiders);
    return foundRiders;
}

lookForRiders(riders).then(foundRiders => {
    // process results here
}).catch(err => {
    // process error here
});

请注意,虽然这看起来更像是在其他语言中使用的同步代码,但它仍然使用异步概念,
lookForRiders()
函数仍然返回一个承诺,您可以使用
访问谁的结果。then()
。这是Javascript中较新的功能,使某些类型的异步代码更易于编写。

它是异步的,在查询完成之前会调用console.log。这就是为什么要传递回调函数
console.log(foundRiders)
附加字符之前执行。findOne
由于是异步的,所以执行起来很精细……。因为为什么不呢!而且nodejs是异步的,我如何延迟它?我来自PHP,这个异步编程需要一些时间来掌握。非常好的答案!不幸的是,这是他们在完整的webdeveloper课程中没有教授的内容。我想我必须继续使用advanced web developer one。@RutgerBrns-因为看起来您可能对堆栈溢出相当陌生,如果这回答了您的问题,那么您可以通过单击答案左侧的复选标记向社区指出这一点。这将“接受”这个答案,并为您在堆栈溢出上赢得一些声誉点数,因为您遵循了这里的正确过程。
async function lookForRiders(riders) {
    let foundRiders = [];
    for (let rider of riders) {
        try {
            let found = await Rider.findOne({_id: rider}).exec();
            foundRiders.push(found);
        } catch(e) {
            console.log(`did not find rider ${rider} in database`);
        }
    }
    console.log(foundRiders);
    return foundRiders;
}

lookForRiders(riders).then(foundRiders => {
    // process results here
}).catch(err => {
    // process error here
});