Axios - 拦截器无法处理请求错误 - 401 代码

med*_*v21 4 reactjs axios

我有一个简单的 React 应用程序,它使用第三个 API 来获取数据。在发出任何请求之前,必须检索令牌才能在标头中使用它。该令牌是使用相同的 API 通过传递客户端 ID 和秘密 ID 创建的 - 该 API 是 Artsy API。此令牌有一个到期日期,因此如果令牌不存在,则必须请求此 API。获得令牌后,我可以毫无问题地调用其他请求。

我已在单独的文件中设置 API 请求,如下所示:Apis.js

import Axios from 'axios';
const baseURL = 'https://api.artsy.net/api';

// set up xap-token and set tot default headers
const instance = Axios.create({
    baseURL: baseURL + '/tokens/xapp_token',
    params: {
        'client_id': process.env.CLIENTID,
        'client_secret': process.env.CLIENTSECRET
    }
});

instance.interceptors.request.use(undefined, err => {
    const status = err.response ? err.response.status : null;
    console.log("auth",err.response)

    if(status === 401){
        console.log("auth",err.response)
        return 'hello'
        // this.getAuthToken();
    }
});

export default{

    getArtworks: function(){
        return new Promise((resolve, reject) => {
            instance.get(baseURL + '/artworks')
            .then(res => {
                resolve(res)
            })
            .catch(err => {
                reject(err);
            });
        });
    },

    getArtists: function(){
        return new Promise((resolve, reject) => {
            instance.get(baseURL + '/artists')
            .then(res => {
                resolve(res)
            })
            .catch(err => {
                reject(err);
            });
        });

    },

    getTest: function(){
        return 'hello';
    }
};
Run Code Online (Sandbox Code Playgroud)

不太确定如何使用createand interceptors,但我创建了一个 Axios 实例。因此,我们的想法是创建某种中间件,创建一个实例,然后在有关于该错误的请求时将其用作拦截器。如果有,则将令牌应用于该实例并继续处理请求retry。也不知道如何在实例中设置令牌。

到目前为止,我在该getArtists方法中收到 401 错误,该 api 在页面加载时被调用,它位于componentDidMount.

应用程序.jsx

import React, { Component } from 'react';
import Apis from './utils/Api';
import Gallery from './components/Gallery';

class App extends Component{
    constructor(props){
        super(props);
        this.state = {
            artWorks: []
        }
    }

    componentDidMount = () => {
        // Apis.getArtists();
        Apis.getArtists().then(res => {
            console.log(res)
            // this.setState({
            //     artWorks: res.data
            // })
        });
    }

    render(){
        return(
            <div>
                <Gallery artists={this.state.artWorks}/>
            </div>
        )
    }
}

export default App;
Run Code Online (Sandbox Code Playgroud)

这是用于身份验证的api文档链接。

有人可以帮忙吗?不太确定如何使用实例作为“中间件”?刚接触 Axios。我想避免使用第三个库中间件,我更喜欢以手动方式学习而不是使用第三个库。非常感谢您的帮助

更新:

我能够让它发挥作用,我修改了instance.interceptor

instance.interceptors.response.use(undefined, err => {
    const status = err.response ? err.response.status : null;
    if(status === 401){
        console.log("auth",err.response)

        instance.post(err.config.authURL, err.config.auth).then(res => {
            let token = res.data.token;
            err.config.headers['X-XAPP-Token'] = token;
            console.log('calling',err.response)
            return instance.request(err.config)
        });
    }

    // return Promise.reject(err);
});
Run Code Online (Sandbox Code Playgroud)

但我的回应变得不确定getArtists。不知道这里发生了什么。这是控制台的屏幕截图:

在此输入图像描述

Min*_*ing 8

您应该使用instance.interceptors.response而不是instance.interceptors.request.

因为请求拦截器是在Ajax请求发送之前调用的。我认为响应拦截器实际上就是您想要的。


  1. 关于BaseURL,你应该像下面这样设置
const instance = Axios.create({
    baseURL: 'https://api.artsy.net/api'
})
// because you set the baseURL of the instance
// this will request url https://api.artsy.net/api/artworks
instance.get('/artworks')
Run Code Online (Sandbox Code Playgroud)
  1. 关于您从您提供的 api 文档中收到的 401 错误。我认为您应该在应用程序启动之前请求获取令牌。
instance.post('tokens/xapp_token').then(res => {
  /* here is the response
{
  "type" : "xapp_token",
  "token" : "...",
  "expires_at" : "2014-09-05T12:39:09.200Z"
}
  */

  // you can set common request headers like this
  // or use request interceptors here to set headers
  // then every request you sent by instance after will have X-XAPP-Token header
  instance.defaults.headers.common['X-XAPP-Token'] = res.token
})
Run Code Online (Sandbox Code Playgroud)

实际上err.config.headers['X-XAPP-Token'] = token;这段代码不会影响请求头。