代码之家  ›  专栏  ›  技术社区  ›  Shawn Matthews

异步/等待阻止执行第二个承诺

  •  0
  • Shawn Matthews  · 技术社区  · 6 年前

    假设我有一个登录函数

    login = () => {
        let url = baseURL + '/user/login?_format=json';  
    
        let data = {
          "name": this.state.email,  
          "pass": this.state.password
        };
    
    
        return axios({
          url,
          method: "POST",
          headers: {
            'Accept':  'application/json',
            'Content-Type': 'application/json',
          },
          withCredentials: true,
          credentials: 'same-origin'
          })
          .then(function(result) {
            console.log('result:', result);
            this.setState({csrfToken: result.data.csrf_token}); 
            this.setState({logoutToken: result.data.logout_token});
            return result;
          })
          .catch(error => console.log('error:', error));
      }; 
    

    然后我想在React中调用onSubmit函数,如下所示。如果函数因任何原因返回错误。在这种情况下,如何阻止下一个函数 api.login() 从被运行?

    {api => (
                <Form
                    onSubmit={async e => {
                      e.preventDefault();
                      await this.login();
                      api.login()
                    }}
                  >
        <input/>
        </Form>
    

    在这种情况下,试一试有意义吗?我尝试了几个选项,包括内联try-catch,一旦承诺从 this.login(); 返回结果或错误。

    3 回复  |  直到 6 年前
        1
  •  1
  •   Sergio Alen    6 年前

    为什么不放 api.login() then

    login = () => {
    let url = baseURL + '/user/login?_format=json';  
    
    let data = {
      "name": this.state.email,  
      "pass": this.state.password
    };
    
    
    return axios({
      url,
      method: "POST",
      headers: {
        'Accept':  'application/json',
        'Content-Type': 'application/json',
      },
      withCredentials: true,
      credentials: 'same-origin'
      })
      .then(function(result) {
        console.log('result:', result);
        this.setState({csrfToken: result.data.csrf_token}); 
        this.setState({logoutToken: result.data.logout_token});
        api.login() // <----- if you want to check result just wrap it in an if statement if (result) api.login()
        return result;
      })
      .catch(error => console.log('error:', error));
    

    };

    否则你可以 login() 要返回布尔值或truthy/falsy值,请执行以下操作(未测试代码):

    {api => (
            <Form
                onSubmit={async e => {
                  e.preventDefault();
                  await this.login() && api.login()  
                }}
              >
    <input/>
    </Form>
    
        2
  •  2
  •   Estus Flask    6 年前

    这就是本文提到的问题 the answer to the previous question

    登录的问题是它的控制流有缺陷。它无法有效地捕捉错误,因为它会抑制错误。

    .catch(error => console.log('error:', error)) 抑制错误,而不应抑制正确的控制流。拒绝应该在使用承诺的顶层处理。即使一个错误需要在 catch (没有必要 console.log 是必要的),它应该被收回。

    在React中,异步错误的一致性处理是一个单独的问题。异步错误需要在生命周期钩子中同步地捕获和重试(可能是 componentDidUpdate ):

      componentDidUpdate() {
        if (this.state && this.state.error) {
          throw this.state.error;
        }
      }
    
      onSubmit = async e => {
        try {
          e.preventDefault();
          await this.login();
          api.login();
        } catch (err) {
          this.setState({ error: err });
        }
      }
    
      render() {
        ...
        <Form onSubmit={this.onSubmit}>
          <input/>
        </Form>
        ...
      }
    

    组件更新 demo

    可能会引入一些额外的助手来干燥 try {...} catch (err) { this.setState({ error: err }) }

        3
  •  1
  •   David Gonzalez    6 年前

    我想这可能是因为你只是在开玩笑控制台.log在catch方法中,不要抛出错误或拒绝承诺。因此,等待的try/catch块继续运行,就好像一切正常一样。尝试抛出一个错误承诺.拒绝或新错误()。

    var catchWithoutRejection = async () => {
      await console.log('hello')
      console.log('running')
    }
    
    catchWithoutRejection();
    
    // hello
    // running
    // Promise {<resolved>: undefined}
    
    var catchWithRejection = async () => {
      await Promise.reject("hello")
      console.log('not running')
    }
    
    catchWithRejection();
    // Promise {<rejected>: "hello"}