Javascript:异步函数混乱

Javascript: Asynchronous function confusion

我有一个调用异步函数(connection.query)的函数,我想修改参数comment并将修改后的值存储在变量res和[=42=中] 它。但是问题是 return 语句在 forEach 完成之前执行,其中有一个异步函数。我如何确保 console.log("outside:" + res);return res; 这两个语句仅在上面的所有内容执行完毕后才会发生。

var res = "";


function testComment(comment) {
    var words = comment.split(" ");
    words.forEach(function(word, i){
        (function(index){
            connection.query('select good_words from words where bad_words = ' + connection.escape(word), function(err, result){
                if(err){
                    console.log(err);
                    return;
                }
                if(result.length != 0){
                    this.res = comment.replace(word, result[0].good_words);
                    console.log("inside:" + this.res);
                }
            });
        })(i);
    });
    console.log("outside:" + this.res);
    return this.res;
}

我试过这样做,我创建了第二个函数,它 return 的值 res 就像这样,

function callback(){
   return res;
}

我修改了 testComment 以接受回调,然后 return 像这样,

function testComment(comment, callback){
  ..all the working..(forEach loop which has a asyn function in it)
  return callback();
}

但是这里的问题是 testComment 会在 forEach 完成之前 return callback(),这让我很困惑。有什么办法可以解决这个问题?

编辑:有关更多上下文,这就是函数的作用, 我在数据库中有一个 table,它有一个 bad_words 列表和一个 good_words 列表,它们替换了输入字符串中的这些 bad_wordscomments 在这个案件)。参数comment是为了测试bad_words,替换成对应的good_words.

你应该使用类似的东西:

var wordsProcessed = 0;
(function(index){
    connection.query('select good_words from words where bad_words = ' + connection.escape(word), function(err, result){
        wordsProcessed++;
        if(err){                 
            console.log(err);
            return;
        }
        if(result.length != 0){
            this.res = comment.replace(word, result[0].good_words);
            console.log("inside:" + this.res);
        }
        if(wordsProcessed >= words.length){
            //THIS IS WHERE YOU RETURN YOUR RES
        }
    });
})(i);

或者更方便,你应该使用 bluebird :)

var Promise = require('bluebird');
var promiseArray = words.map(function(word){
    return new Promise(function(resolve, reject){
        connection.query('select good_words from words where bad_words = ' + connection.escape(word), function(err, result){
            if(err) reject(err);
            else resolve(result);
        }); 
    });
});

Promise.all(promiseArray).then(function(result){
    return this.res;
});