1

我在componentdidmount中有ajax调用。然后在 ajax 承诺中设置状态。

代码是这样的

componentDidMount(){
    axios.post('mydomian.com/item/',this.state)
    .then(function (response) {
        const res = response.data
        if (res.status === 'OK') {
            this.setState({items :res.list})
        }else{
            console.log('can not load data', response)
        }
    }.bind(this))
}
componentWillUnmount(){
    how to stop everything about axios?
}

当我导航到其他路线时,这会导致错误“无法在未安装的组件上设置状态”。

所以我认为我应该做的是在componentwillunmount中移除axios监听器。你会怎么做?

4

2 回答 2

7

一个非常简单的解决方案可能是在卸载时设置一个标志并在承诺解决方案中使用它,如下所示:

componentDidMount(){
    axios.post('mydomian.com/item/',this.state)
    .then(function (response) {
        if (this.unmounted) return;
        const res = response.data
        if (res.status === 'OK') {
            this.setState({items :res.list})
        }else{
            console.log('can not load data', response)
        }
    }.bind(this))
}
componentWillUnmount(){
    this.unmounted = true;
}
于 2016-06-12T06:25:36.730 回答
1

我找到了 istarkov 定义的一个很好的解决方案

const makeCancelable = (promise) => {
  let hasCanceled_ = false;

  const wrappedPromise = new Promise((resolve, reject) => {
    promise.then((val) =>
      hasCanceled_ ? reject({isCanceled: true}) : resolve(val)
    );
    promise.catch((error) =>
      hasCanceled_ ? reject({isCanceled: true}) : reject(error)
    );
  });

  return {
    promise: wrappedPromise,
    cancel() {
      hasCanceled_ = true;
    },
  };
};

如何使用:

const somePromise = new Promise(r => setTimeout(r, 1000));

const cancelable = makeCancelable(somePromise);

cancelable
  .promise
  .then(() => console.log('resolved'))
  .catch(({isCanceled, ...error}) => console.log('isCanceled', isCanceled));

// Cancel promise
cancelable.cancel();

在那里找到了解决方案。

我的实现。

在我的功能里面

const promiseShareByEmail = makeCancelable(this.props.requestShareByEmail(obj.email, obj.url));

            promiseShareByEmail.promise.then(response => {
                const res = response.data;

                if (res.code != 0)
                    throw new Error(res.message);
                this.setState({
                    message: {
                        text: TextMeasurements.en.common.success_share_test,
                        code: Constants.ALERT_CODE_SUCCESS
                    }
                });
            }).catch(err => {
                if (err.isCanceled)
                    return;

                this.setState({
                    message: {
                        text: err.message,
                        code: Constants.ALERT_CODE_ERROR
                    }
                })
            });

            this.promiseShareByEmail = promiseShareByEmail;

this.props.requestShareByEmail(obj.email, obj.url)该函数从 axios 返回承诺。

当组件将卸载取消功能应该被调用。

componentWillUnmount() {
        this.promiseShareByEmail.cancel();
    }

请享用。

于 2017-01-19T14:14:20.200 回答