【问题标题】:Create promise for api in React app在 React 应用程序中为 api 创建 promise
【发布时间】:2018-03-30 19:53:45
【问题描述】:

我正在为 Web 应用程序构建身份验证,当我将登录数据发送到服务器时卡住了,但我无法异步执行,因为我创建的函数不返回承诺。

所以我想要完成的是当我填写表单时按下按钮并执行函数 onSubmit(),它验证输入的数据,然后如果一切正常,则执行传递的函数 submit()。然后函数 submit() 执行 api.user.login(data) 函数,将数据发送到服务器并接收有关用户注册状态的信息。如果登录状态为成功,用户将被重定向到用户页面,但是当调用 api.user.login() 时我被卡住了,它不返回承诺。

当我提交表单数据时,出现如下错误。但是服务器仍然接收表单数据。

TypeError: Cannot read property 'then' of undefined
LoginPage._this.submit
src/components/pages/LoginPage.js:17
  14 | }
  15 | 
  16 | submit = data => {
> 17 |   api.user.login(data)
  18 |   .then(res => {
  19 |     if (res.data === "loginSucces") {
  20 |       <Redirect to="/user"/>
View compiled
LoginForm._this.onSubmit
src/components/pages/forms/LoginForm.js:26
  23 | 
  24 | //is empty method or ES6 Object.keys(errs) takes all the keys
  25 | if (Object.keys(errors).length === 0) {
> 26 |   this.props.submit(this.state.data)
  27 |   // console.log("hello");
  28 |   // this.props.submit()
  29 | }

我试图做的是将登录函数包装在 new Promise() 中,但这绝对行不通。

    return new Promise((resolve, rejec) => {
           let data = JSON.stringify(credentials);
           axios.post("/register", data
           ).then(function(res) {
               console.log(res);
               return res.data
           }).catch(function(error) {
               console.log(error);
            });

})

所以我的登录页面代码如下:

import React from 'react';
import LoginForm from './forms/LoginForm';
import PropTypes from "prop-types"
import api from "../../api.js"
import { Route, Redirect } from 'react-router'

class LoginPage  extends React.Component
{
    constructor(){
        super();
        this.state = {

        };
    }

    submit = data => {
      api.user.login(data).then(res => {
        if (res === "loginSucces") {
          <Redirect to="/user"/>
        }
      }).cache(err=>{
        console.error(err);
      })
    }

    render() {
        return (
          <div>
              <h1>Login page</h1>
              <LoginForm submit={this.submit}/>
          </div>
        );
    }
}

export default LoginPage;

登录表单代码:

import React from 'react';
import PropTypes from "prop-types";
import {Button, Form, FormGroup, Label, Input, FormFeedback} from 'reactstrap';

class LoginForm extends React.Component{
    constructor(){
        super();
        this.state = {
            data:{},
            loading: false,
            errors: {}
        };
    }

    onChange = e =>
        this.setState({
            data: {...this.state.data, [e.target.name]: e.target.value}})

    onSubmit = e => {
        e.preventDefault();
        const errors = this.validate(this.state.data);
        this.setState({ errors: errors })

        //is empty method or ES6 Object.keys(errs) takes all the keys
        if (Object.keys(errors).length === 0) {
          this.props.submit(this.state.data)
          // console.log("hello");
          // this.props.submit()
        }
    }

    validate = (data) => {
        const errors = {};

        //TODO cant be special sibols, to short etc
        if(!data.username) {
            errors.username = "Can't be bank";
        }
        if(!data.password){
            errors.password = "Can't be bank";
        }

        return errors;
    }

    render() {

        return(

            //TODO form still reloads

            <Form onSubmit={this.onSubmit}>
                <FormGroup>
                    <Label for="username">Username</Label>
                    <Input
                            invalid={!!this.state.errors.username}
                            name="username"
                           id="username"
                           placeholder="What is your username?"
                           value = {this.state.data.username}
                           onChange = {this.onChange}
                    />
                    <FormFeedback invalid >{this.state.errors.username}</FormFeedback>
                </FormGroup>
                <FormGroup>
                    <Label for="password">Password</Label>
                    <Input invalid={!!this.state.errors.password}
                        type="password"
                        name="password"
                        id="password"
                        placeholder="Make it secure"
                        value = {this.state.data.password}
                        onChange = {this.onChange}
                    />
                    <FormFeedback invalid >{this.state.errors.password}</FormFeedback>
                </FormGroup>
                <Button preventDefault>Submit</Button>
            </Form>
        )
    }
}

LoginForm.propTypes = {
  submit: PropTypes.func.isRequired
};

export default LoginForm;

API 代码:

import axios from "axios"

export default {
    user: {
        login: credentials =>{
                let data = JSON.stringify(credentials);
                axios.post("/register", data
                ).then(function(res) {
                  console.log(res);
                  return res.data
                }).catch(function(error) {
                  console.log(error);
                });
              },
          test: () => {console.log("test in api")}
    }
}

这是 console.log(res) 输出:

{
  data: "loginSucces",
  status: 200,
  statusText: "OK",
  headers: {
    …
  },
  config: {
    …
  },
  …
}config: adapter: ƒxhrAdapter(config)arguments: (...)caller: (...)length: 1name: "xhrAdapter"prototype: {
  constructor: ƒ
}__proto__: ƒ()[
  [
    FunctionLocation
  ]
]: xhr.js: 11[
  [
    Scopes
  ]
]: Scopes[
  2
]data: "{"username":"sdfsdfdfsdfsdfsdgsdfgsdgsadgsdgsdag","password":"sdfsdfsdfsdf345235235"}"headers: Accept: "application/json, text/plain, */*"Content-Type: "application/x-www-form-urlencoded"__proto__: ObjectmaxContentLength: -1method: "post"timeout: 0transformRequest: {
  0: ƒ
}transformResponse: {
  0: ƒ
}url: "/register"validateStatus: ƒvalidateStatus(status)xsrfCookieName: "XSRF-TOKEN"xsrfHeaderName: "X-XSRF-TOKEN"__proto__: Objectdata: "loginSucces"headers: connection: "close"content-length: "11"content-type: "text/html; charset=utf-8"date: "Fri, 30 Mar 2018 20:03:56 GMT"etag: "W/"b-JeyKc7pdZbjTvd8ActAidnhWojA""vary: "Accept-Encoding"x-powered-by: "Express"__proto__: Objectrequest: XMLHttpRequestonabort: nullonerror: ƒhandleError()onload: nullonloadend: nullonloadstart: nullonprogress: nullonreadystatechange: ƒhandleLoad()ontimeout: ƒhandleTimeout()readyState: 4response: "loginSucces"responseText: "loginSucces"responseType: ""responseURL: "http://localhost:3000/register"responseXML: nullstatus: 200statusText: "OK"timeout: 0upload: XMLHttpRequestUploadonabort: nullonerror: nullonload: nullonloadend: nullonloadstart: nullonprogress: nullontimeout: null__proto__: XMLHttpRequestUploadwithCredentials: false__proto__: XMLHttpRequeststatus: 200statusText: "OK"__proto__: constructor: ƒObject()hasOwnProperty: ƒhasOwnProperty()isPrototypeOf: ƒisPrototypeOf()propertyIsEnumerable: ƒpropertyIsEnumerable()toLocaleString: ƒtoLocaleString()toString: ƒtoString()valueOf: ƒvalueOf()__defineGetter__: ƒ__defineGetter__()__defineSetter__: ƒ__defineSetter__()__lookupGetter__: ƒ__lookupGetter__()__lookupSetter__: ƒ__lookupSetter__()get__proto__: ƒ__proto__()set__proto__: ƒ__proto__()

【问题讨论】:

  • console.log(res) 收到的回复是什么?
  • 刚刚检查,对服务器的请求工作正常,我可以将表单数据发送到服务器,服务器发回确认。
  • 请参阅已编辑的问题。
  • 将此行 if (res === "loginSucces") 更改为 if (res.data === "loginSucces")
  • 是的,这是一个错误,但它不会影响这个问题,因为如果没有承诺,我不能使用 .then()。

标签: javascript reactjs api asynchronous login


【解决方案1】:

有些事情你需要知道

axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 node.js

  • 从浏览器发出 XMLHttpRequests
  • 从 node.js 发出 http 请求
  • 支持 Promise API
  • 拦截请求和响应
    • 转换请求和响应数据
  • 取消请求
  • JSON 数据的自动转换
  • 客户端支持防止 XSRF

Axios 不会返回 Promise。

关于post的官方实现

执行 POST 请求

axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

您的实现代码如下:

login: credentials =>{
    let data = JSON.stringify(credentials);
    axios.post("/register", data
    ).then(function(res) {
      console.log(res);
      return res.data
    }).catch(function(error) {
      console.log(error);
    });
  },

好像输出是data属性的内容。

参考资料:

https://github.com/axios/axios

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 2016-11-02
    • 2017-04-14
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 2020-12-22
    相关资源
    最近更新 更多