【问题标题】:Handling error from async await syntax with axios使用 axios 处理来自异步等待语法的错误
【发布时间】:2019-03-01 21:32:19
【问题描述】:

这是我的代码块:

  const getToken = async () => {
    try {
      const token = await axios.post(keys.sessionURL, {
        email: keys.verificationEmail,
        password: keys.verificationPassword,
      });
    } catch (err) {
      throw new Error('Unable to establish a login session.'); // here I'd like to send the error to the user instead
    }
  };

如您所见,我正在连接到外部服务器以获取令牌。那行得通。现在,我想捕获一个错误,但这次不是“抛出新错误”,而是我想将它发送给用户,所以我想要这样的东西:

res.status(401).send('Unable to get a token');

但是因为我不在路由处理程序中,所以我不能使用“res”。那我怎样才能把它发送给用户呢?

谢谢!

【问题讨论】:

  • 您可以在路由处理程序中等待 getToken 并在那里捕获异常。然后你就可以访问你的 res 对象了。如果您提供有关如何调用 getToken 的更多信息,我可以向您展示一个示例

标签: node.js express


【解决方案1】:

优雅且带有 TypeScript。

import axios, { AxiosResponse } from "axios";
...

const response: void | AxiosResponse<any, any> = await axios({
  headers: {
    Authorization: `Bearer ${XYZ}`,
    Accept: "application/json",
  },
  method: "GET",
  params: {
    ...
  },
  url: "https://api.abcd.com/...",
}).catch((error: unknown) => {
  if (error instanceof Error) {
    console.error(
      "Error with fetching ..., details: ",
      error
    );
  }
});

【讨论】:

    【解决方案2】:

    保持async / await的优雅:

    const result = await axios.post('/url', params)
        .catch((err) => {
           // deal with err, such as toggle loading state, recover click and scroll.
           this.loading = false;
           // recover the reject state before.
           return Promise.reject(err);
        });
    
    this.data = result; // not exec when reject
    

    【讨论】:

      【解决方案3】:

      try/catch 不是一个好的解决方案。它的目的是捕获运行时错误,而不是来自 axios 的 HTTP 错误,如果错误由拦截器处理,然后通过 return Promise.reject(error); 传递回调用者@

      这里是拦截器示例

      axios.interceptors.response.use(
        response => {
          //maybe process here
          return response;
        },
        error => {
          //do some global magic with error and pass back to caller
          return Promise.reject(error);
        }
      );
      

      让我们从 try/catch 不起作用的示例开始

      for(let i=0; i<5;i++) {
      
          try{
             const result = async axios.get(`${/item/{i}}`);
          }
          catch(error) {
             //error undefined here, you would expect an error from pattern like axios.get(...).then(...).catch(real_http_error) 
          }
      }
      

      我发现这种模式行得通。假设由于 JS 的异步特性,您想循环调用以避免多次 http 调用。

      for(let i=0; i<5;i++) {
      
          const result = async axios.get(`${/item/{i}}`).catch(error) {  //chain catch despite async keyword
             //now you access http error and you can do something with it
             //but calling break; or return; won't break for loop because you are in a callback
          }
      
          if(!result) { //due to http error
              continute; //keep looping for next call
              //or break; to stop processing after 1st error
          }
          
          //process response here, result.data...
      }
      

      【讨论】:

      • 很好的答案,因为在这种情况下,您不需要将每个 axios 函数都包装到 try / catch 中。使用它。
      【解决方案4】:

      对于 axios 版本-0.19.0,经过数小时的异步等待后,代码工作正常。但不确定其他版本!

      catch(error){
      console.log(error.response.data.error)
      }
      

      希望有帮助!

      【讨论】:

      • 我觉得这是迄今为止这个问题的最佳答案。与其他人不同,它实际上使用触发错误提供的数据,并允许进一步处理。好一个,Akshay ?
      • 答案应该被投票为正确答案。它允许前端检索来自后端的错误。这保存了我的项目
      • 挣扎了一个小时,这救了我!
      • 显示错误 TypeError: Cannot read properties of undefined (reading 'data')
      【解决方案5】:

      在我的解决方案中我使用:

      try{
          let responseData = await axios.get(this.apiBookGetBookPages + bookId, headers);
          console.log(responseData);
      }catch(error){
          console.log(Object.keys(error), error.message);
      }
      

      如果某些事情失败了,我们会得到这样的错误:

      [ 'config', 'request', 'response', 'isAxiosError', 'toJSON' ] 
      'Request failed with status code 401'
      

      我们也可以获取状态码:

      ...
      }catch(error){
          if(error.response && error.response.status == 401){
                  console.log('Token not valid!');
          }
      }
      

      【讨论】:

        【解决方案6】:

        你可以保持几乎相同的功能

        const getToken = async () => {
          try {
            const token = await axios.post(keys.sessionURL, {
              email: keys.verificationEmail,
              password: keys.verificationPassword,
            })
          } catch (err) {
            throw new Error('Unable to get a token.')
          }
        }
        

        然后从您的路由处理程序中 catch 最终异常

        app.get('/endpoint', async (req, res) => {
          try {
            const token = await getToken()
        
            // Do your stuff with the token
            // ...
        
          } catch (err) {
             // Error handling here
             return res.status(401).send(err.message);
          }
        })
        

        默认的js异常系统可以很好的通过调用栈传递错误数据。

        【讨论】:

          【解决方案7】:

          您保留isAuthError 之类的标志,如果发生错误,则将其作为真发送,如果标志isAuthError 为真,则在主函数中抛出错误并在 catch 中处理,否则执行您的操作。我在下面添加了一个示例。希望对你有帮助

          const getToken = async () => {
              try {
                const token = await axios.post(keys.sessionURL, {
                  email: keys.verificationEmail,
                  password: keys.verificationPassword,
                });
                return {token, isAuthError: false};
              } catch (err) {
                // throw new Error('Unable to establish a login session.'); // here I'd like to send the error to the user instead
                return {err, isAuthError: true};
              }
            };
          

          主函数

          app.post('/login', async (req, res)=>{
            try{
              // some validations
          
              let data = await getToken();
              if( data.isAuthError){
                throw data.err;
              }
              let token = data.token;
              //do further required operations
            }catch(err){
               //handle your error here with whatever status you need
               return res.status(500).send(err);
            }
          })
          

          【讨论】:

          • 这听起来像是需要额外步骤的错误处理:)
          猜你喜欢
          • 2018-07-29
          • 2022-01-09
          • 2018-04-06
          • 2017-06-08
          • 1970-01-01
          • 2018-02-15
          • 1970-01-01
          • 2017-05-25
          • 1970-01-01
          相关资源
          最近更新 更多