【问题标题】:Async await in Express middleware not workingExpress中间件中的异步等待不起作用
【发布时间】:2018-09-23 00:17:55
【问题描述】:

我是 Node 的新手,所以要温柔。我正在为我的婚礼创建一个应用程序,它接收上传的宾客名单(Excel 文件格式)并将其转换为 JSON 数组,然后我可以使用该数组来构建每位宾客的个人资料(饮食要求、rsvp 答案等)。

到目前为止,我的主页上有一个表单,允许用户上传 .xlsx 文件,当提交表单时,用户会再次重定向回主页。

我创建了以下路线:

router.post('/',
    guestsController.upload,
    guestsController.getGuestlist,
    guestsController.displayGuestlist
);

这是我的客人控制器:

const multer = require('multer');
const convertExcel = require('excel-as-json').processFile;

const storage = multer.diskStorage({ //multers disk storage settings
    destination: function (req, file, cb) {
      cb(null, './uploads/')
    },
    filename: function (req, file, cb) {
        var datetimestamp = Date.now();
        cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
    }
});

exports.upload = multer({storage: storage}).single('file');

exports.getGuestlist = async (req, res, next) => {

  try {
     await convertExcel(req.file.path, null, null, (err, guestData) => {
         req.guestlist = guestData.map((guestObj) => Object.values(guestObj)[0]);
     });
     console.log(req.guestlist);
     next();
  } catch (e){
    res.json({error_code:1,err_desc:"Corrupted Excel file"});
    next();
  }
};

exports.displayGuestlist = (req, res) => {
    console.log(req.guestlist);
};

目前由于函数的同步特性,displayGuestlist 正在将 undefined 返回到控制台,因为covertExcel 尚未完成抓取数据。你可以看到我已经尝试使用新的 async await 语法来解决这个问题,但不幸的是它没有修复它。

我还尝试将 displayGuestlist 中的日志放在超时函数中,这已证明这纯粹是一个时间问题。

任何帮助者将不胜感激。

【问题讨论】:

    标签: javascript node.js express async-await


    【解决方案1】:

    看起来convertExcel 不是一个返回 Promise 的函数,而是使用了一个老式的回调函数。 await 不适用于这些,因此它正在等待 Promise.resolve(undefined),因为该函数返回 undefined,而不是 Promise。值得庆幸的是,在 Node 8 及更高版本中,有一个 promisify 实用程序可以将回调样式函数转换为 Promise 返回函数,以便可以使用 await

    const { promisify } = require('util');
    const convertExcel = promisify(require('excel-as-json').processFile);
    
    // ...
    
    const guestData = await convertExcel(req.file.path, null, null);
    req.guestlist = guestData.map((guestObj) => Object.values(guestObj)[0]);
    

    【讨论】:

    • 啊太棒了。是的,这实际上完全有道理。谢谢,我会拉下那些包并试一试。
    • util 是 Node 内置的一个包,所以你不需要安装任何东西。
    • 非常感谢雅各布。像魅力一样工作!
    【解决方案2】:

    您可以将您的代码封装在一个 Promise 中并等待该 Promise 解决。

    exports.getGuestlist = async (req, res, next) => {
    let promise = new Promise((resolve, reject) => {
        convertExcel(req.file.path, null, null, (err, guestData) => {
            if(err) reject(err);
            else resolve(guestData);
        });
    });
    try {
        let guestData = await promise;
        req.guestlist = guestData.map((guestObj) => Object.values(guestObj)[0]); 
        console.log(req.guestlist);
        next();
    } catch (e){
        res.json({error_code:1,err_desc:"Corrupted Excel file"});
        next();
        }
    };
    

    【讨论】:

    • 我想这会很公平。正如雅各布解释的那样,问题的原因是我试图等待一个没有返回承诺的函数。因此,将所有内容都包含在一个 Promise 中也可以。谢谢恩里克
    • 完美地解决了这个问题,无需任何额外的库!
    猜你喜欢
    • 2018-01-27
    • 2023-04-07
    • 2018-01-02
    • 1970-01-01
    • 1970-01-01
    • 2019-07-20
    • 1970-01-01
    相关资源
    最近更新 更多