Nodejs for循环问题

Nodejs for循环问题


for (var i = 0; i < 2; i++) {
console.log(“循环:”,i)
result_1[i] = []

	use(_match[i],"match",_lotterytype[i], function(result) 
	{
		// console.log("循环:",i)
		console.log("match:",i)
		// console.log(result);
		result_1[i].push(result)

		use(_sort[i],"sort",_lotterytype[i], function(result) 
		{
			console.log("sort:",i)
			// console.log(result);
			result_1[i].push(result)

			use(_option[i],"option",_lotterytype[i], function(result) 
			{
				console.log("option:",i)
				// console.log(result);

				result_1[i].push(result)
				// ser.emit("done",result_1)
			})//option
		})//sort
	})//match
};

use是一个函数,函数内部会读取文件。

让我不能理解的是,输出结果会是

循环: 0 循环: 1 match: 2

按说在每次循环的时候都应该输出 一次 console.log(“match:”,i) console.log(“sort:”,i) console.log(“option:”,i) 才对啊 为什么看起来就好像for循环跑过头了似的?

小弟对于nodejs的for循环异步还是有些不甚理解,还望各位指点一二。


3 回复

您提到的问题是因为 for 循环中的异步操作导致的。在您的代码中,use 函数是异步的,这意味着当循环执行到 use 函数时,它不会立即阻塞等待 use 完成,而是继续执行下一个循环迭代。这会导致在所有异步操作完成之前,循环已经结束。

让我们详细分析一下代码,并提供一个改进后的版本来解决这个问题。

原始代码的问题

for (var i = 0; i < 2; i++) {
    console.log("循环:", i);
    result_1[i] = [];

    use(_match[i], "match", _lotterytype[i], function(result) {
        console.log("match:", i);
        result_1[i].push(result);

        use(_sort[i], "sort", _lotterytype[i], function(result) {
            console.log("sort:", i);
            result_1[i].push(result);

            use(_option[i], "option", _lotterytype[i], function(result) {
                console.log("option:", i);
                result_1[i].push(result);
                // ser.emit("done", result_1);
            }); // option
        }); // sort
    }); // match
}

解决方案

您可以使用 async/awaitPromise 来处理这些异步操作,以确保每个循环迭代中的异步操作按顺序完成。

改进后的代码

const asyncFunctionRunner = async () => {
    let result_1 = [];

    for (let i = 0; i < 2; i++) {
        console.log("循环:", i);
        result_1[i] = [];

        await new Promise((resolve, reject) => {
            use(_match[i], "match", _lotterytype[i], async (result) => {
                console.log("match:", i);
                result_1[i].push(result);

                await new Promise((resolve, reject) => {
                    use(_sort[i], "sort", _lotterytype[i], async (result) => {
                        console.log("sort:", i);
                        result_1[i].push(result);

                        await new Promise((resolve, reject) => {
                            use(_option[i], "option", _lotterytype[i], async (result) => {
                                console.log("option:", i);
                                result_1[i].push(result);
                                resolve();
                            }); // option
                        }); // sort
                    }); // sort
                }); // match
            }); // match
        }); // promise wrapper
    }

    // ser.emit("done", result_1);
};

asyncFunctionRunner();

解释

  1. 异步函数:我们定义了一个名为 asyncFunctionRunner 的异步函数。
  2. 循环:在循环中,我们使用 await 关键字来等待每个异步操作完成。
  3. Promise 包装器:为了使 use 函数的回调能够与 await 一起使用,我们将每个 use 调用包装在一个新的 Promise 中。
  4. 按顺序执行:通过这种方式,我们可以确保每个异步操作在继续下一个操作之前都已完成。

这样,您就可以确保每个 use 调用都在前一个调用完成后执行,从而避免了异步操作导致的混乱输出。


这个输出是对的。因为 node 只有在 cpu 操作都完成之后,才会去响应异步的事件。

在Node.js中,由于JavaScript的事件循环机制,for循环中的异步操作(如回调函数)可能会导致你看到不符合预期的结果。具体来说,在你的例子中,use函数是异步的,这意味着for循环会立即执行完所有迭代,并且在这些迭代结束之前不会等待异步操作完成。

为了更好地理解这一点,可以考虑以下几点:

  1. for循环会立即执行完所有迭代。
  2. 每次调用use时,都会将一个异步操作添加到事件队列中。
  3. 由于异步操作不是立即完成的,for循环可能在所有异步操作完成之前就结束了。

这会导致你在循环结束后才看到异步操作的结果。你可以通过使用闭包或者使用async/await来解决这个问题。以下是使用闭包和async/await的示例:

使用闭包

for (let i = 0; i < 2; i++) {
    (function(i) {
        console.log("循环:", i);
        result_1[i] = [];

        use(_match[i], "match", _lotterytype[i], function(result) {
            console.log("match:", i);
            result_1[i].push(result);

            use(_sort[i], "sort", _lotterytype[i], function(result) {
                console.log("sort:", i);
                result_1[i].push(result);

                use(_option[i], "option", _lotterytype[i], function(result) {
                    console.log("option:", i);
                    result_1[i].push(result);
                    // ser.emit("done", result_1);
                });
            });
        });
    })(i);
}

使用 async/await

async function process() {
    for (let i = 0; i < 2; i++) {
        console.log("循环:", i);
        result_1[i] = [];

        await new Promise((resolve) => {
            use(_match[i], "match", _lotterytype[i], function(result) {
                console.log("match:", i);
                result_1[i].push(result);

                use(_sort[i], "sort", _lotterytype[i], function(result) {
                    console.log("sort:", i);
                    result_1[i].push(result);

                    use(_option[i], "option", _lotterytype[i], function(result) {
                        console.log("option:", i);
                        result_1[i].push(result);
                        resolve();
                    });
                });
            });
        });
    }
}

process();

在这个示例中,我们使用了async/await来确保每个异步操作完成后才会继续下一个迭代。这样可以确保每个异步操作的结果按顺序输出。

回到顶部