未处理拒绝承诺异步等待链

时间:2018-09-17 18:37:25

标签: node.js async-await

我刚开始使用javascript等待异步,所以这个问题可能是我不知道的。

我有这个

  async foo(req, res, next) {
    try {
      await scan(req.params.stack);
      res.send('ok');
    } catch (err) {
      res.status(500).send('fail');
    }
  }

async scan(stack) {
  try {
    const libs = [1,2,3];
    const promises = libs.map(async l => analyze(stack, l)
      .catch((err) => { throw new Error(err); }));
    return q.allSettled(promises)
      .then((results) => {
        const rejected = results.filter(r => r.state === 'rejected');
        if (rejected.length === results.length) throw new Error('Failed');
        return results;
      })
      .catch((err) => {
        throw new Error(err);
      });
  } catch (err) {
    throw new Error(err);
  }
}

async function analyze(stack, libraries) {
  try {
    const config = await buildConfiguration(stack, libraries);
    return await databaseInsertion(vulnsObject);
  } catch (err) {
    return Promise.reject('Error while trying to analyze libs');
  }
}

我不知何故得到了这个疯狂的警告,我不知道在哪里没有发现错误。

我当然要使构建配置失败以测试错误,但是我没有正常的流程来解决错误,我得到了:

(node:415) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: Error while trying to analyze libs

我使用异步等待好吗?我应该遵循什么模式才能将异步链式等待?

疯狂的是foo函数运行良好,这意味着res.status。(500).send('fail');工作,我得到回应

当我使用正常的诺言时,不会出现此错误。

我真的被困在这里

3 个答案:

答案 0 :(得分:4)

使用CREATE TABLE foo (a varchar(4000), a_ax AS (IIF(PATINDEX('%bar%', a) > 0, SUBSTRING(a, PATINDEX('%bar%', a), 42), ''))) CREATE INDEX foo_x ON foo(a_ax) 扫描功能时,您正在将async-await .then()瀑布与.catch()混合在一起。 await处理的承诺与async-await一样好。因此,请坚持使用一种流程,并尝试将一种功能或另一种功能混合使用。

.then()

答案 1 :(得分:1)

调用async函数(此处为analyze)将返回一个promise,它将根据async函数的返回值或是否抛出错误来解决或拒绝。

现在,analyze函数正在处理引发的错误,但是在引发错误时它将返回Promise.reject()Promise.reject()是此处未处理的拒绝,这是日志所说明的。

就同步功能而言,等效项将为

function sync() {
  try {
    // do something dangerous
  } catch (ex) {
    throw Error('Something bad happened'); // this error is still being thrown and nobody is handling it
  }
}

要处理此错误,您可以在调用同步时执行以下操作,将其包装在try中,然后再次捕获

try {
  sync();
} catch (ex) {
  console.error(ex); // not gonna throw another exception, otherwise the program might crash
}

现在,等效于analyze函数的此包装将使用另一个异步函数,或者更好,因为调用async函数将返回一个Promise,请使用{{1} } catch

的方法
Promise

更好的做法是首先不返回analyze() .then(() => console.log('My work is done here')) .catch(ex => console.error(ex)); // NOTE: not throwing another exception 的拒绝,从而使catch

analyze

答案 2 :(得分:0)

在analyzer()中,您将返回Project.reject(),但analyze()是异步函数。因此,它可以解析您返回的任何值,并拒绝您引发的任何错误。

    async function analyze(stack, libraries) {
        try {
            const config = await buildConfiguration(stack, libraries);
            return await databaseInsertion(vulnsObject);
        } catch (err) {
            return Promise.reject('Error while trying to analyze libs');
        }
    }

因此,当analytics函数遇到错误时,您将创建拒绝项,然后再解决该函数。因此Promise.reject('Error while trying to analyze libs');未得到处理。由于异步函数总是返回一个承诺,该承诺将根据您返回的内容进行解析,并拒绝您所抛出的任何内容,因此您的analyse函数将始终进行解析。尝试做这个...

    async function analyze(stack, libraries) {
        try {
            const config = await buildConfiguration(stack, libraries);
            return await databaseInsertion(vulnsObject);
        } catch (err) {
            throw Error('Error while trying to analyze libs');
        }
    }

我在代码中看到的另一件事可能是即使您向map(async func)传递了一个异步函数,它也不在乎。在调用下一个函数之前,它不会等待每个函数完成。

const promises = libs.map(async l => analyze(stack, l)
      .catch((err) => { throw new Error(err); }));
    return q.allSettled(promises)
      .then((results) => {
        const rejected = results.filter(r => r.state === 'rejected');
        if (rejected.length === results.length) throw new Error('Failed');
        return results;
      })
      .catch((err) => {
        throw new Error(err);
      });

下面有两个变化

const promises = libs.map(async l => await analyze(stack, l)
      .catch((err) => { throw new Error(err); }));
    return q.allSettled( await promises)
      .then((results) => {
        const rejected = results.filter(r => r.state === 'rejected');
        if (rejected.length === results.length) throw new Error('Failed');
        return results;
      })
      .catch((err) => {
        throw new Error(err);
      });

我在分析函数之前添加了一个等待,并在将promises变量传递到q.allSettled()中之前添加了一个等待。