Javascript: путаница асинхронных функций

#javascript #asynchronous #node-mysql

#javascript #асинхронный #узел-mysql

Вопрос:

У меня есть функция, которая вызывает асинхронную функцию ( connection.query ), я хочу изменить параметр comment и сохранить измененное значение в переменной res и вернуть его. Однако проблема в том, что оператор 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;
}
  

Я попытался сделать это, я создал вторую функцию, которая возвращает значение res вот так,

 function callback(){
   return res;
}
  

и я изменил testComment , чтобы принять обратный вызов, а затем вернуть его следующим образом,

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

Но здесь проблема в том, что testComment вернет callback() перед forEach завершением, это действительно сбивает меня с толку. Есть ли способ это исправить?

РЕДАКТИРОВАТЬ: Для большего контекста, это то, что делает функция, у меня есть таблица в базе данных, в которой есть список bad_words и список, good_words которые заменяют их bad_words во входной строке ( comments в данном случае). Параметр comment должен быть протестирован на bad_words и заменен соответствующим good_words .

Комментарии:

1. попробуйте использовать обычный цикл for: //этот цикл является синхронизирующим по своей природе для(var i=0,len=words. длина; я

Ответ №1:

Вы должны использовать что-то вроде:

 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;
});
  

Комментарии:

1. Большое вам спасибо, сэр, вы спасли мне жизнь!