javascript - Nodejs 异步 waterfall 回调函数未定义

标签 javascript node.js asynchronous waterfall

我正在尝试将文件及其详细信息保存在数据库中。

waterfall 函数有两次调用,但第二个函数不等待第一个函数完成。

即使不使用 waterfall ,每个系列也无法按预期工作。它不会等待记录被创建,因此由于相同的 id 会发生唯一性错误。 我在这里做错了什么以及如何解决它?

谢谢!

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

最佳答案

更新的答案:

我重写了代码。 我忘记了 async.js 以不同的方式处理 Promise。基本上,您不使用callback()。请改用 return 。如果发生错误,请使用抛出新的Error(message)。 请参阅here了解更多信息。阅读主题:使用 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) {
...

其次,您不应该返回回调。回调是一个函数而不是一个 promise 。正常使用即可。

<小时/>

顺便说一下,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();

关于javascript - Nodejs 异步 waterfall 回调函数未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53370636/

相关文章:

javascript - Node.js - 设置系统日期/时间

javascript - 文本编辑器错误

javascript - 如何恢复已被网站禁用的 console.log() 功能?

mysql - 显示信息。使用 nodeJS 从 mySQL 数据库到网页

java - RxJava中如何同步异步方法? RxJava 中的异步瀑布

c# - 自动重新连接异步套接字客户端

c# - 我可以异步运行同步代码以获得性能吗?

javascript - window.location.reload 完成了吗?

asp.net - 如何使用asp.net mvc转到下拉选择的其他页面

javascript - 我无法启动我的 js Discord 机器人,出现错误消息