Функция обратного вызова асинхронного водопада Nodejs не определена - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь сохранить файл и сведения о нем в базе данных.

Функция водопада с двумя вызовами, но вторая функция не ожидает завершения первой функции.

Даже без водопада каждая серия не работает должным образом. Он не ожидает создания записи и, следовательно, возникает ошибка уникальности из-за того же идентификатора. Что я тут не так делаю и как это исправить?

Спасибо!

       async.eachSeries(uploadedPhotos, async function (uploadedFile, callback) {

          async.waterfall([
            async function() {
              var lastUser = await TblUserFiles.find({}).sort('id DESC').limit(1);
              // fileID remains undefined if i remove async-await from the  function 
              var fileID = lastUser[0].id;
              fileID += 1;
              cbb(null, fileID, uploadedFile);
            },
            async function(file_id, uploadedFile, cbb) {
              sails.log("save file id is " + file_id);
              sails.log("savee file id is " + uploadedFile['filename']);
              var today = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
              await TblUserFiles.findOrCreate({ customer_no: req.session.userId, file_type: 'profile_image' }, {
                id: fileID,
                customer_no: req.session.userId,
                file_name: uploadedFile['filename'],
                file_type: 'profile_image',
                is_approved: 'No',
                approved_by: 0,
                approved_on: today,
                approved_from: ip,
                uploaded_date: today,
                modified_date: today
              }).exec(async (err, user, wasCreated) => {
                if (err) { return res.serverError(err); }

                if (wasCreated) {
                  // created a new user
                  sails.log("new file was uploaded...")
                  return cbb(err, "done");

                  // return res.send("sent");
                }
                else {
                  // found existing user
                  var user = await TblUserFiles.create({
                    id: fileID,
                    customer_no: req.session.userId,
                    file_name: uploadedFile["filename"],
                    file_type: "image",
                    is_approved: "No",
                    approved_by: 0,
                    approved_on: today,
                    approved_from: ip,
                    uploaded_date: today,
                    modified_date: today
                  }).intercept(err => {
                    // Return a modified error here (or a special exit signal)
                    // and .create() will throw that instead
                    err.message = "Uh oh: " + err.message;
                    return err;
                  }).fetch();
                  if (user) {
                    sails.log("found existing files..")
                    return cbb(err, "done");
                  }
                  sails.log("this should not be called");
                }
              });
            }
          ], (err, success) => {
            if (err) sails.log(err);
            return callback(err, 'done')
          });



        }, function (err) {
          // if any of the saves produced an error, err would equal that error
          if (err) {
            sails.log(err);
          } else {
            return res.json({
              message: uploadedPhotos.length + ' file(s) uploaded successfully!',
              files: uploadedPhotos
            });
          }
        });

1 Ответ

0 голосов
/ 19 ноября 2018

Обновленный ответ:

Я переписываю код. Я забыл, что async.js обрабатывает обещание по-другому. По сути, вы не используете callback(). Вместо этого используйте return. Если возникает ошибка, используйте throw new Error(message). См. здесь для получения дополнительной информации. Читайте тему: Использование асинхронных функций ES2017 .

async.eachSeries(uploadedPhotos, async uploadedFile => {
  var lastUser = await TblUserFiles.find({}).sort('id DESC').limit(1);
  var fileID = lastUser[0].id;
  fileID += 1;
  sails.log("save file id is " + file_id);
  sails.log("savee file id is " + uploadedFile['filename']);
  var today = moment(new Date()).format('YYYY-MM-DD HH:mm:ss');
  await TblUserFiles.findOrCreate(
    { customer_no: req.session.userId, file_type: 'profile_image' },
    {
      id: fileID,
      customer_no: req.session.userId,
      file_name: uploadedFile['filename'],
      file_type: 'profile_image',
      is_approved: 'No',
      approved_by: 0,
      approved_on: today,
      approved_from: ip,
      uploaded_date: today,
      modified_date: today
    }
  ).exec(async (err, user, wasCreated) => {
    if (err) throw new Error(err);
    if (wasCreated) {
      sails.log("new file was uploaded...");
      return;
    } else {
      await TblUserFiles.create({
        id: fileID,
        customer_no: req.session.userId,
        file_name: uploadedFile["filename"],
        file_type: "image",
        is_approved: "No",
        approved_by: 0,
        approved_on: today,
        approved_from: ip,
        uploaded_date: today,
        modified_date: today
      })
      .intercept(err => {
        throw new Error("Uh oh: " + err.message);
      }).fetch();
      if (user) {
        sails.log("found existing files..");
        return;
      } else {
        sails.log("this should not be called");
        return;
      }
    }
  });
}, err => {
  // Don't call res.serverError() or res.json() inside the async loop!
  if (err) {
    sails.log(err);
    res.serverError(err);
  }
  else {
    res.json({
      message: uploadedPhotos.length + ' file(s) uploaded successfully!',
      files: uploadedPhotos
    });
  }
});

Я думаю, что первая проблема заключается в том, что вы забыли дать первой задаче функцию обратного вызова (в данном случае cbb).

async.waterfall([
            async function(cbb) {
              var lastUser = await TblUserFiles.find({}).sort('id DESC').limit(1);
              // fileID remains undefined if i remove async-await from the  function 
              var fileID = lastUser[0].id;
              fileID += 1;
              cbb(null, fileID, uploadedFile);
            },
            async function(file_id, uploadedFile, cbb) {
...

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


Кстати, const async = require('async'); НЕ переопределит ключевое слово async. Компилятор может сказать разницу между ними. Это подтверждается следующим примером сценария:

const async = require('async');

let runPromise = (name, timer, success = true) => {
  console.log(`${name} starts.`);
  return new Promise((resolve, reject) => {
    if (success) {
      setTimeout(function () {
        resolve(`${name} finished after ${timer / 1000} seconds(resolved).`);
      }, timer);
    } else {
      reject(`${name} failed(rejected).`);
    }
  });
};

async function asyncFunction() {
  let txt = await runPromise('A', 1000);
  console.log(txt);
}

asyncFunction();
...