ES7 async await如何catch异常

asdfg
  • 229

比如我有以下代码:

async function check(){
    let promises = _.map(rules, async(rule) => {
        throw new Error('aaaaaa');
    });
    return promises;
}

async function doCheck(){
    let result;
    try{
         result = await Promise.all(check());
    }
    catch(e){
        console.log('error occurs');
    }  
}

上面代码执行的时候 console.log('error occurs')是捕获不到的,我有什么办法可以拿到check()方法中报出的异常呢?

回复
阅读 14.9k
2 个回答
✓ 已被采纳

要获取async函数的返回值,调用的时候,必须要await才能获取,否则获取到的是一个Promise封装过的对象,应该改成这样:

async function check(){
    let promises = _.map(rules, async(rule) => {
        throw new Error('aaaaaa');
    });
    return promises;
}

async function doCheck(){
    let result;
    try{
         result = await Promise.all(await check());//await获取promises
    }
    catch(e){
        console.log('error occurs');
    }  
}

上面那样写是对了,不过显得冗余了,因为check函数本身(排除内部函数的代码)并没有await操作,其实不必声明为async,可以去掉check的async声明。

function check(){
    let promises = _.map(rules, async(rule) => {
        throw new Error('aaaaaa');
    });
    return promises;
}

async function doCheck(){
    let result;
    try{
         result = await Promise.all(check());
    }
    catch(e){
        console.log('error occurs');
    }  
}

或者改成这样,把Promise.all写在check里,我觉得这样更好。

async function check(){
    let promises = _.map(rules, async(rule) => {
        throw new Error('aaaaaa');
    });
    return await Promise.all(promises);
}

async function doCheck(){
    let result;
    try{
         result = await check();
    }
    catch(e){
        console.log('error occurs');
    }  
}

测试结果

国外有人提出一个解决方案:

import to from 'await-to-js';

async function asyncTaskWithCb(cb) {
     let err, user, savedUser, notification;

     [ err, user ] = await to(UserModel.findById(1));
     if(!user) return cb('No user found');

     [ err, savedTask ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
     if(err) return cb('Error occurred while saving task');

    if(user.notificationsEnabled) {
       [ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
       if(err) return cb('Error while sending notification');
    }

    if(savedTask.assignedUser.id !== user.id) {
       [ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
       if(err) return cb('Error while sending notification');
    }

    cb(null, savedTask);
}

async function asyncFunctionWithThrow() {
  const [err, user] = await to(UserModel.findById(1));
  if (!user) throw new Error('User not found');
  
}

这是GitHub地址

但我感觉这种方式还是要写很多err条件判断,不如promise.catch优雅。或者可以这样写:

import to from 'await-to-js';

async function asyncTaskWithCb2(cb) {
     let err, user, savedUser, notification;

     [ err, user = {} ] = await to(UserModel.findById(1));
     // if(!user) return cb('No user found');

     [ err, savedTask = { assignedUser: {} } ] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));

    if(user.notificationsEnabled) {
       [ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
    } else {
       cb('No user found');
    }

    if(savedTask.assignedUser.id !== user.id) {
       [ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
    }

    cb(err, savedTask);
}
宣传栏