代码之家  ›  专栏  ›  技术社区  ›  Julian Mendez

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

  •  7
  • Julian Mendez  · 技术社区  · 8 年前

      async function foo(req, res, next) {
        try {
          await scan(req.params.stack);
          res.send('ok');
        } catch (err) {
          res.status(500).send('fail');
        }
      }
    
    async function 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 回复  |  直到 5 年前
        1
  •  4
  •   NAVIN    8 年前

    使用时 async-await .then() .catch() 瀑布 await . .然后() . 因此,坚持一个流程,并尝试在一个函数中混合这两个流程,或者在另一个函数中混合这两个流程。

    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];
    
        // This libs.map functions return promise. then why not use await?
        const promises = await libs.map(async l => analyze(stack, l);
    
        // Again q.allSettled returns promise, use await here too
        let results = await q.allSettled(promises);
    
        const rejected = results.filter(r => r.state === 'rejected');
    
        if (rejected.length === results.length) throw new Error('Failed');
    
        return results;
    
      }
    
      // If any promise call reject function will be in catch
      catch (err) {
        throw new Error(err);
      }
    }
    
    async function analyze(stack, libraries) {
        try {
            const config = await buildConfiguration(stack, libraries);
            return await databaseInsertion(vulnsObject);
        }
        catch (err) {
            console.log(err);
            return null;
        }
    }
    
        2
  •  1
  •   Akshendra Pratap    8 年前

    打电话给 async analyze )将返回一个承诺,该承诺将根据 异步的

    现在 分析 函数正在处理抛出的错误,但它将返回 Promise.reject() 当抛出错误时。A. 这里是未处理的拒绝,这是日志所述。

    就同步函数而言,等效函数为

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

    要处理此错误,您可以在调用sync时执行以下操作,将其包装在try-and-catch中,然后重试

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

    现在,对于 分析 函数将使用另一个异步函数,或者自调用 异步的 函数将返回一个 Promise catch a方法 允诺

    analyze()
      .then(() => console.log('My work is done here'))
      .catch(ex => console.error(ex)); // NOTE: not throwing another exception
    

    更好的做法是不要退回来自客户的拒绝 抓住 首先,这样做 分析 ,

    async function analyze(stack, libraries) {
      try {
        const config = await buildConfiguration(stack, libraries);
        return await databaseInsertion(vulnsObject);
      } catch (err) {
        console.error(err); // not eating up good errors with something vague is always good
        return null; // or something else to signify that insert failed
      }
    }
    
        3
  •  0
  •   Fred    8 年前

    在analyze()中,返回的是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');
            }
        }
    

    Promise.reject('Error while trying to analyze libs'); 没有得到处理。由于异步函数总是返回一个承诺,该承诺会解决您返回的任何内容,并拒绝您抛出的任何内容,因此您的分析函数总是会解决这个问题。试试这个。。。

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

    我在analyze函数之前添加了一个wait,在将promises变量传递到 q.allSettled() .

    推荐文章