проблема с асинхронным водопадом при запросе к БД

Я создаю набор объектов для сохранения в mongoDB из потока csv. Для каждой строки csv мне нужно проверить перед сохранением, что объект или объекты не существуют в MongoDB. Приведенный ниже код выполняется внутри маршрута GET.

Я пытался использовать асинхронный водопад, но он ведет себя не так, как я ожидал.

Вот код

    async.waterfall([
        function (callback) {

            console.log('in function 1');
        -->  Diagnosis.findOne({name: diagnosisName}, function (doc){
                console.log(JSON.stringify(doc))
            })
            callback(null);

        },
        function (callback) {

            console.log('in function2')
            callback(null)
        }],

    function(err, results) {
        console.log('finished!')
        res.send("complete");
    })

Я ожидаю, что это вернет следующее

в функции1

объект документа в формате JSON

в функции2

законченный!

вместо этого я получаю

в функции 1

в функции2

законченный!

нулевой

он работает, как и ожидалось, пока нет вызова findOne(). Что мне не хватает??

Очень признателен


person Pierre Davidoff    schedule 17.06.2015    source источник


Ответы (2)


findOne — это асинхронная функция. Вам нужно будет переместить обратный вызов внутри этой функции, чтобы следовать ожидаемому порядку.

async.waterfall([
    function(callback) {
      console.log('in function 1');
      Diagnosis.findOne({name: diagnosisName}, function(doc) {
        console.log(JSON.stringify(doc));
        callback(null);
      });

    },
    function(callback) {

      console.log('in function2');
      callback(null);
    }
  ],

  function(err, results) {
    console.log('finished!');
    res.send("complete");
  }
);

Но почему бы не использовать внутреннее обещание (или другую библиотеку обещаний)?

console.log('in function 1');
// exec creates a new promise
Diagnosis.findOne({name: diagnosisName}).exec(function(doc) {
  console.log(JSON.stringify(doc));
  // resolve this with doc
  return doc;
}).then(function(doc) {
  console.log('in function2');
  // resolve this with doc
  return doc;
}).then(results) {
  // results here is just doc from the previous resolution
  console.log('finished!');
  res.send("complete");
});
person Jason Cust    schedule 17.06.2015

В вашей первой функции:

    function (callback) {

        console.log('in function 1');
    -->  Diagnosis.findOne({name: diagnosisName}, function (doc){
            console.log(JSON.stringify(doc))
        })
        callback(null);

    },

Ваш обратный вызов вызывается после вызова findOne, который является асинхронным. Вы должны просто использовать свой обратный вызов всякий раз, когда findOne выполняется. Что значит:

    function (callback) {

        console.log('in function 1');
    -->  Diagnosis.findOne({name: diagnosisName}, function (doc){
            console.log(JSON.stringify(doc))
            callback(null);
        })


    },

Или даже лучше

    function (callback) {

        console.log('in function 1');
    -->  Diagnosis.findOne({name: diagnosisName}, callback);


    },
    function (callback, doc) {
        console.log(JSON.stringify(doc))
        callback(null);
    },
person Alex    schedule 17.06.2015
comment
Подпись вашей второй функции неверна. Должна быть функция (документ, обратный вызов), НЕ функция (обратный вызов, документ) - person Ben; 18.06.2015