Nodejs 请教mongoose查询中回调函数怎样能拿到查询参数的值?

Nodejs 请教mongoose查询中回调函数怎样能拿到查询参数的值?

我需要在一个for循环中进行数据库查询,如果没有匹配把对应的index存进一个数组。

for ( var index = 0; index < 100; index++) {
    mongooseModel.findOne({ id: index }, function (err, model) {
        if (!model) {
            array.push(index);
        }
    });
}

由于mongoose的回调函数是异步的,我这么写存的index值是有问题的。有什么办法能把查询参数传给回调函数呢?


3 回复

当然可以!你遇到的问题是因为 findOne 方法是异步的,而你的 for 循环会立即执行完毕,导致所有的回调函数在执行时都使用了最后一次的 index 值。

为了解决这个问题,你可以使用闭包或者箭头函数来捕获每次循环中的 index 值。下面是两种方法的具体实现:

方法一:使用闭包

for (var index = 0; index < 100; index++) {
    (function(index) { // 立即执行函数表达式创建闭包
        mongooseModel.findOne({ id: index }, function (err, model) {
            if (!model) {
                array.push(index);
            }
        });
    })(index); // 传递当前的 index 值
}

方法二:使用箭头函数(ES6)

for (let index = 0; index < 100; index++) { // 使用 let 关键字
    mongooseModel.findOne({ id: index }, (err, model) => {
        if (!model) {
            array.push(index);
        }
    });
}

解释

  1. 闭包:通过创建一个立即执行函数表达式(IIFE),将当前的 index 值作为参数传递进去。这样每次循环都会创建一个新的作用域,从而保留当前的 index 值。

  2. 箭头函数:使用 let 替换 var 可以让 index 在每次迭代时都有一个新的绑定。箭头函数会继承外部作用域的 index 值,而不是每次都引用循环变量的最后值。

这两种方法都可以确保每次回调函数都能正确地获取到当前的 index 值。希望这对你有所帮助!


试一下async模块:https://github.com/caolan/async

<pre><code> var list = [0…100]; async.map(list, function (callback) { mongooseModel.findOne({ id: index }, callback); }, function (err, results) { //results.filter(function (item) {return item;});//如果有需要过滤空值的话,当然也可以用async.filter //results就是你想要的 }); </pre></code>

在使用 Mongoose 进行查询时,由于回调函数是异步执行的,直接在循环中使用 index 变量会导致所有回调函数都拿到循环结束后的最终 index 值。为了解决这个问题,可以在循环中使用闭包来捕获每次迭代中的 index 值。

下面是具体的示例代码:

for (var index = 0; index < 100; index++) {
    // 使用闭包捕获当前的index值
    (function(currentIndex) {
        mongooseModel.findOne({ id: currentIndex }, function(err, model) {
            if (!model) {
                array.push(currentIndex);
            }
        });
    })(index); // 立即调用函数表达式,并传入当前的index值
}

在这个示例中,我们创建了一个立即执行的函数表达式(IIFE),它接受 currentIndex 作为参数,并将该参数传给回调函数。这样,在每次迭代中,currentIndex 都会捕获当前的 index 值,从而确保每个回调函数都能拿到正确的 index 值。

另外,如果你使用的是较新的 JavaScript 版本,可以使用 let 来声明 index,因为 let 具有块级作用域,可以避免变量提升的问题。

for (let index = 0; index < 100; index++) {
    mongooseModel.findOne({ id: index }, function(err, model) {
        if (!model) {
            array.push(index);
        }
    });
}

这样,在每次迭代中,index 的值都会被正确捕获,而不会被后续迭代覆盖。

回到顶部