Javascript 当for循环在节点js中完成时调用函数
在这段代码中,我在for循环之后调用了函数sample(),但在for循环结束之前调用了sample()函数Javascript 当for循环在节点js中完成时调用函数,javascript,node.js,function,for-loop,Javascript,Node.js,Function,For Loop,在这段代码中,我在for循环之后调用了函数sample(),但在for循环结束之前调用了sample()函数 我想在for循环结束时调用sample()函数。我是stackoverflow的初学者,如果我有错误,请向我道歉。谢谢您很可能遇到此问题,因为您的db.query()函数不同步。它需要一个回调函数,完成后可以调用该函数 在数据库库查询数据库并获得结果之前,不会调用您的代码inboxUserList.push(…)。同时,for循环将继续运行,准备好所有查询并在它们全部完成之前继续。然后调
我想在for循环结束时调用sample()函数。我是stackoverflow的初学者,如果我有错误,请向我道歉。谢谢您很可能遇到此问题,因为您的
db.query()
函数不同步。它需要一个回调函数,完成后可以调用该函数
在数据库库查询数据库并获得结果之前,不会调用您的代码inboxUserList.push(…)
。同时,for循环将继续运行,准备好所有查询并在它们全部完成之前继续。然后调用sample()
,因为for循环已经完成,即使传入的回调尚未调用
有许多解决方案,但也许当前代码最简单的解决方案如下:
same function
single user1
single user2
single user3
函数inboxUsers(){
var完成=0;
对于(var i=0;i您对db.query
的调用是异步的。这意味着:
对db.query(…)
的调用立即返回,不返回任何内容
您没有将返回值赋给变量(var results=db.query(…)
),而是将作为参数传入,以便db模块在获取结果后可以调用。它将挂起回调函数,直到数据库获得结果,然后在准备好时调用该函数
由于对db.query(…)
的调用将立即返回,因此for循环将完成,对sample()
的调用将在db模块调用您提供给查询的回调函数之前启动
要确保sample
在所有调用完成时运行,您需要跟踪每个查询的完成情况,然后在所有查询返回时启动sample
函数。我认为,最简单的方法是在不向您介绍“承诺”等复杂主题的情况下执行此操作,具有名为的模块及其方法
$npm安装异步--保存
这里是再次,但采取较少的捷径和详细的评论
var async = require('async');
var queries = [];
function inboxUsers(){
uniqueArray.forEach(function (userId) {
var getUsername = 'SELECT userName FROM users WHERE userId = ' + userId;
queries.push(function (done) {
db.query(getUsername, done);
});
});
async.parallel(queries, function (err, allQueryResults) {
if (err) { return console.error(err); }
allQueryResults.forEach(function (queryResults) {
queryResults.forEach(function (result) {
console.log('single', result.userName);
inboxUserList.push(result.userName);
});
});
sample();
});
}
function sample(){
console.log('same function');
}
async
lib知道您向数组提供了多少函数,因此它知道在调用最终函数之前应该等待多少次对done
的调用。欢迎使用StackOverfow!请更新您的问题,将输出包括到控制台,或者描述您如何知道调用了该函数示例循环结束之前。for
循环将始终在示例运行之前完成;db.query
,但是,它似乎是异步的,这意味着示例将在您传递给它的回调之前运行。@dVid我更新了我的问题。这些包括控制台输出请参见下面的答案。这是一个非常常见的问题可以轻松修复的异步场景:)我遇到了这个错误,TypeError:undefined不是inboxUsers(C:\Users\yathu\IdeaProjects\chatting\app.js:148:16)
,这是一行148:})。然后(function(){@user3702886您在数据库中使用什么库?var mysql=require('mysql'));在这种情况下,您甚至不需要使用.then
或.on
。只需将completed++
和下面的if
语句向上移动到for循环下面的查询回调函数中。这样,您就可以完全避免承诺和事件处理程序,这对于初学者来说有些复杂。@AlexFord这是一个很好的观点!我简化了我的示例以反映这一点。在数组中使用相同的用户名,在sample()中打印inboxUserList,我得到了这个结果['kabilan','kabilan','kabilan']
我还更改了(var I=0;Iconsole.log('single',result.username'))
此行打印未定义我无法识别示例中的错误,并且我无法测试它,因为我没有您正在运行的完整代码。我将首先检查传递给async.parallel
回调(allQueryResults
)的内容然后看看它是什么样子。它应该是一个数组数组。每个嵌套数组都是相关查询的结果。尝试console.log(result);
也可以查看result
是什么。如果它不是您期望的,那么我们可以从那里找到原因。
function inboxUsers(){
var completed = 0;
for (var i=0; i<uniqueArray.length; i++){
var getUsername = 'SELECT userName FROM users WHERE userId = ' + uniqueArray[i];
db.query(getUsername, function(err, results) {
if (err) {
console.log('Error in database');
throw err;
}
for(var i in results){
console.log('single',results[i].userName);
inboxUserList.push(results[i].userName);
}
completed++;
if (completed == uniqueArray.length) {
sample();
}
});
}
}
function sample(){
console.log('same function');
}
var async = require('async');
var queries = [];
function inboxUsers(){
uniqueArray.forEach(function (userId) {
var getUsername = 'SELECT userName FROM users WHERE userId = ' + userId;
queries.push(function (done) {
db.query(getUsername, done);
});
});
async.parallel(queries, function (err, allQueryResults) {
if (err) { return console.error(err); }
allQueryResults.forEach(function (queryResults) {
queryResults.forEach(function (result) {
console.log('single', result.userName);
inboxUserList.push(result.userName);
});
});
sample();
});
}
function sample(){
console.log('same function');
}
var async = require('async');
// create an array to store a bunch of functions that the async library
// should fire and wait to finish.
var queries = [];
function inboxUsers(){
uniqueArray.forEach(function (userId) {
var getUsername = 'SELECT userName FROM users WHERE userId = ' + userId;
var queryFunc = function (done) {
db.query(getUsername, function(err, results) {
// let the async lib know this query has finished.
// the first argument is expected to be an error.
// If the err is null or undefined then the async lib
// will ignore it. The second argument should be our results.
done(err, results);
});
// You could make the above even simpler by just passing
// the done function as the callback to db.query. I just
// didn't want to confuse you by doing that.
// db.query(getUsername, done);
};
queries.push(queryFunc);
});
// Fire all async functions by passing in our queries array.
// The async library will wait for them all to call "done()"
// before it invokes this final function below.
async.parallel(queries, function (err, allQueryResults) {
// If any of our queries pass an error to "done" then the async
// lib will halt the rest of the queries and immediately invoke
// this function, passing in the error.
if (err) { return console.error(err); }
// queryResults is an array containing the results of each query we made.
allQueryResults.forEach(function (queryResults) {
queryResults.forEach(function (result) {
console.log('single', result.userName);
inboxUserList.push(result.userName);
});
});
// All your queries are complete and your inboxUserList array
// is populated with the data you were after. Now we can call
// "sample".
sample();
});
}
function sample(){
console.log('same function');
}