承诺-如何处理已知错误

时间:2018-08-08 13:14:40

标签: javascript error-handling promise async-await try-catch

我了解承诺的工作原理,但我并没有完全了解处理已知错误的最佳/预期方式是……应如何处理它们。

示例:
假设函数fetch('/api/login')返回一个诺言,(为简单起见)它可以通过{status: 200}{status: 500}{status: 401}来解析(这意味着凭据不正确)

我如何处理不同情况的想法是:

const login = async () => {
  try {
    const res = await fetch('/login')
    if (res.status === 200) {
      return Promise.resolve()
    } else if (res.status === 401) {
      return Promise.reject('INCORRECT_CREDENTIALS') // throw should work here too
    } else {
      throw new Error('Request failed')
    }
  } catch (e) {
    if (e instanceof Error) {
      console.error('Something really bad happened', e)
      return Promise.reject() // discard the error
    } else {
      throw e // it's a known error, pass it down
    }
  }
}

// Somewhere inside a LoginForm component
try {
  await login()
  redirectSomewhere() // Successful login
} catch (e) {
  if (e === 'INCORRECT_CREDENTIALS') {
    showIncorrectCredentialsText()
  }
  // ignore other errors
}

然后我尝试使用bluebird实现它,并得到以下警告:a promise was rejected with a non-error,根据their explanation,promise应该只拒绝Error个对象。为什么呢由于调试。但是,此INCORRECT_CREDENTIALS错误不是需要调试的未知错误。我什至都不认为这完全是错误,诺言因为任何原因login失败而拒绝了。这是否意味着对于我要处理的每个已知错误,promise应使用{error: 'ERROR_CODE'}来解决?如果是这样,catch处理单个错误是什么意思?如果每个错误都是“想调试” ...

我知道我可以创建自己的IncorrectCredentialsError,但是如果我真的不在乎某些stacktrace的话,我看不出有什么好处。

我在这里有点困惑,所以请任何人快速介绍一下正确的错误处理应该是什么样子? :)

1 个答案:

答案 0 :(得分:0)

目前,您正在使用async / await语法,但使用的是Promise的bluebird实现。因此,您不得不使用错误对象来拒绝承诺和bluebird API中描述的所有其他bluebird风格的东西。

根据您的情况,我会在以下三个选项之间进行选择:

1)将bluebird用于所有内容,删除async / await语法,并通过拒绝错误对象和bluebird提供的所有其他功能来使用bluebird错误处理。

2)对try / catch使用async / await语法:

// API
const HTTP_ERRORS = {
    "404": "RESOURCE_NOT_FOUND",
    "500": "INTERNAL_SERVER_ERROR"
};
const login = async () => {
    const response = await fetch( '/login' );
    const status = response.status;
    if ( !status ) throw new Error( "INVALID RESPONSE" );
    else if ( status === 200 ) return JSON.parse( response.responseText );
    else return HTTP_ERRORS[ JSON.stringify( status ) ]; // or throw new Error( HTTP_ERRORS[ JSON.stringify( status )]); 
};
// workflow
try {
    const profile = await login();
}
catch( error ) {
    console.error( error );
}

3)直接使用本机承诺:

// API
const HTTP_ERRORS = {
    "404": "RESOURCE_NOT_FOUND",
    "500": "INTERNAL_SERVER_ERROR"
};
const login = () => fetch( '/login' )
    .then( response => {
        const status = response.status;
        if ( !status ) throw new Error( "INVALID RESPONSE" );
        else if ( status === 200 ) return JSON.parse( response.responseText );
        else throw new Error( HTTP_ERRORS[ JSON.stringify( status )]);
    });
// workflow
login()
    .then( profile => { console.log( 'ok' ); })
    .catch( error => console.error( error ));

任何一种解决方案都可以,只要您保持一致即可。 以我的拙见,将所有这些组合随机组合在一个项目中只会使下一个调试您的代码的人感到困惑。