在fetch返回的promise上使用then()会返回React

时间:2019-06-21 04:31:02

标签: javascript reactjs promise jwt fetch

我正在关注本教程:https://github.com/callicoder/spring-security-react-ant-design-polls-app

我已经有一个可以生成JWT的工作后端,并且API还使用GET方法在http://localhost:8080/api/user/me中返回了当前用户的详细信息。背面一切都很好(已通过Postman测试)。

但是,当我尝试将当前用户从API加载到App组件的状态时,我遇到了问题。这个想法是创建到Login组件的路由,并将其传递给对handleLogin方法的引用,该方法执行getCurrentUser()并重定向到主页。

所有这些操作都是通过导入名为APIUtils的文件来完成的,该文件具有与API交互的方法。特别是,它具有通用的request()方法,该方法使用获取返回承诺,并接收请求的参数。问题是我无法得到APIUtils/request()方法返回的诺言的响应。它说它是未定义的。

App.js

//imports
class App extends Component {
  state = {
    currentUser: null
  }

  loadCurrentUser = () => {
    // getCurrentUser is imported from APIUtils/index.js
    getCurrentUser()
      .then(response => {
        this.setState({
          currentUser: response
        });
      })
      .catch(error => {
        console.log(error)
      });
  }

  handleLogin = () => {
        this.loadCurrentUser();
    this.props.history.push("/");
  }

  componentDidMount() {
    this.loadCurrentUser();
  }

  render () {
    return (
      <Switch>
        <Route exact path='/' component={Landing} />
        <Route path="/login" 
          render={
            (props) => <Login onLogin={this.handleLogin} {...props} />
        }/>
        </Route>
      </Switch>
    );
  }
}

export default withRouter(App);

APIUtils / index.js

const request = (options) => {
    const headers = new Headers({
            'Content-Type': 'application/json',
    })

    if(localStorage.getItem(ACCESS_TOKEN)) {
        headers.append('Authorization', 'Bearer ' + localStorage.getItem(ACCESS_TOKEN))
    }

    const defaults = { headers: headers };
    options = Object.assign({}, defaults, options);

    return fetch(options.url, options)
    .then(response => {
        response.json().then(json => {
            if(!response.ok) {
                return Promise.reject(json);
            }
            return json;
        })}
    );
}

// expects loginRequest = { email: 'something', password: 'something' }
export const login = (loginRequest) => {
    return request({
            url: API_BASE_URL + "/auth/signin",
            method: 'POST',
            body: JSON.stringify(loginRequest)
    });
}

export const getCurrentUser = () => {
    if(!localStorage.getItem(ACCESS_TOKEN)) {
        return Promise.reject("No access token set.");
    }
    return request({
            url: API_BASE_URL + "/user/me",
            method: 'GET'
    });
}

Login.js

class Login extends Component {

    state = {
        email: '',
        password: ''
    }

    handleChange = (event) => {
        this.setState({
            [event.target.id]: event.target.value
        });
    }

    handleSubmit = (event) => {
        event.preventDefault();
        const loginRequest = Object.assign({}, this.state);

        login(loginRequest)
            .then(response => {
                localStorage.setItem(ACCESS_TOKEN, response.accessToken);
                this.props.onLogin();
            }).catch(error => {
                if(error.status === 401) {
                    console.log('Your Username or Password is incorrect. Please try again!');
                } else {
                    console.log('Sorry! Something went wrong. Please try again!');                                         
                }
            });
    }

  render () {
        return (
            <React.Fragment>
        /* 
        * form using onSubmit={this.handleSubmit}
        * inputs using value={this.state.email} and onChange={this.handleChange}
        * button of type="submit"
        */
            </React.Fragment>
        );
    } 
}
export default Login;

有了这个,我登录并加载控制台后,通过控制台检查了登录并将本地令牌存储在本地存储中,APIUtils中的request()方法也返回了URL响应:http://localhost:8080/api/user/me ,并返回代码中的json承诺,如下所示:

{
  "id": 23,
  "name": "john",
  "email": "new@mail.com"
}

但是当我尝试使用then()访问App.js中getCurrentUser()的响应时,它的响应是不确定的,因此我无法将其设置为状态。

1 个答案:

答案 0 :(得分:1)

您没有返回fetch()的结果:

return fetch(options.url, options)
    .then(response => { // you forgot that this is also a function
        return response.json().then(json => { // <--- missing return!!
            if(!response.ok) {
                return Promise.reject(json);
            }
            return json;
        })}
    );

我可以理解为什么您可能会错过它。很容易错过。这就是为什么您应该使用Promises的主要功能-发明它们的原因-Promise链的原因:

let ok = null;
return fetch(options.url, options)
    .then(response => {
        ok = response.ok;
        return response.json();
    })
    .then(json => {
        if (!ok) {
            return Promise.reject(json);
        }
        return json;
    });

通过这种方式更容易发现缺失的回报,因为您可以轻松地检查每个then块是否具有return陈述。