api控制器中的Nodejs异步/等待响应未知错误

时间:2018-03-20 09:38:50

标签: node.js async-await

export function getAllHost(req, res) {
    function findAllHost() {
        let query = {};

        query.company = req.query && req.query.companyId ? req.query.companyId : res.locals.payload.companyId;
        query.active = true;

        if(req.query && req.query.name) {
            let regexp = new RegExp('\\b' + req.query.name);
            query['name'] = {$regex: regexp, $options: 'i'};
        }

        return Host.find(query);
    }

    async function sendRes() {
        let allHost = [];
        let hosts = [];
        try {
                hosts = await findAllHost();
        } catch(err){
                console.log(err)
        }
        for (let host of hosts) {
            allHost.push(new Host_V1(host));
        }
        return allHost
    }

    sendRes().then(data => res.status(200).json(data)).catch(error => {
        console.log("error is", error);
        res.status(error.status || 500).json({
            message: error.status ? error.message : 'Server Error'
        });
    });
}

我一直在尝试将async / await改编为我的代码,所以我转换了一个基于Promise的api控制器来使用async/await,但困扰我的是我的服务器以500响应,而我的catch块中的console.log不会打印任何内容。

不会抛出任何错误。

我正在使用babel babel-plugin-syntax-async-functions来解析它。

我做错了什么?

2 个答案:

答案 0 :(得分:1)

您的代码有点过于复杂,但根据它判断,如果出现错误,您应该在控制台中收到错误。它可能是你有一个中间件产生错误?主要问题是您正在捕获异步函数sendRes中的错误,因此即使出现错误,您在返回的Promise上调用的.catch - 方法也不会被触发。
像许多其他async/await的新用户一样,您误解并相信您已经将每个await表达式包装在try/catch块中。不是这种情况。错误“涓流”调用链,除非特定函数可以提供不同的返回值,否则最好从最顶层的被调用者捕获错误。举一个显示常见反模式的简单示例:https://repl.it/repls/PunySafeInterfacestandard(在这些示例中甚至不需要等待和异步,但为了清楚起见我添加了它们)

但是如果你试图简化你的代码,可能就像下面的代码片段一样,你可以排除它是否是中间件。

export async function getAllHosts (req, res) {
  try {
    let query = {
      company: req.query && req.query.companyId ? req.query.companyId : res.locals.payload.companyId,
      active: true
    }

    if (req.query && req.query.name) {
      let regexp = new RegExp('\\b' + req.query.name)
      query.name = {$regex: regexp, $options: 'i'}
    }

    let allHosts = (await Host.find(query)).map((host) => new Host_V1(host))
    return res.json(allHosts)
  } catch (e) {
    console.log("error is", e)
    res.status(error.status || 500).json({
      message: error.status ? error.message : 'Server Error'
    })
  }
}

记下(await Host.find(query))行。如果从Host.find()返回的Promise拒绝,则.map() - 方法将不会对数据执行,执行将跳转到catch - 块。

我也非常不鼓励使用Babel,因为自7.6版本以来,async/await已在Node中得到本地支持。

答案 1 :(得分:0)

编辑:返回的值确实是一个承诺

我认为该错误与您的“SendRes.then”相关。因为SendRes返回的内容不是一个承诺,但它实际上是数组allHost

由于你的async / await实现,你的数据参数不再是一个参数,它是sendRes函数返回的值。

const hosts = sendRes();
res.status(200).json(hosts);

如果你想处理一个错误,你必须从catch块中返回一些内容,以便你可以在这里处理它。

if (!hosts) res.status(500);

为简化您的代码,您还可以摆脱sendRes函数,并使您的getAllHost表达中间件成为异步函数

async getAllHost(req, res) { /*...*/ }

try {
    let allHosts = await findAllHosts();
    res.status(200).json(allHosts);
} catch (error) {
    res.status(500).send({ error })
}