React组件挂载优化

做惯了react的首屏加载优化、代码结构优化、dom diff优化,却很少从react组件挂载做切入点动些邪念,嘻嘻嘻。。。。

所以今天被问及这个问题时,回答的就有点隔靴搔痒,没能直击面试官的G点。。。。

当时我答定义一个isMounted变量来判断组件的运行状态。。。。

当然能解决问题,但不是最优解。。。。

回来后翻阅资料,发现有高手封装了cancelableFetch工具来处理异步请求。。。。

我猜想作者是打算在组件componentWillUnmount后cancel这个请求。。。。

思路是正确的,但是有个bug。。。。

当路由在response后和setState前切换的话,一样会报错。。。。

所以也不是最优解。。。。

继续翻阅后,看到有大神使用AbortController api的。。。。

貌似是完美解决问题。。。。

cancelableFetch代码如下:

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

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

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

export default makeCancelable;

AbortController使用方式如下:

componentDidMount() {
  this.controller = new AbortController();
  let signal = this.controller.signal;

  setTimeout( () => {
      fetch( Config.YAHOO + Config.NEWS + this.id + Config.YAHOO_SUFFIX, { signal } )
        .then( res => { return res.json() } )
        .then( data => { this.setState( { json: data.query.results.json } ); } )
        .catch( e => console.log( e, 'is canceled.............' ) )
    },
    5000 )
}

componentWillUnmount() {
  this.controller.abort();
}
方法二一个signal可以标记多个异步请求,简单方便,可以说是完美解决问题,墙裂推荐!

猜你喜欢

转载自blog.csdn.net/songshuzhong/article/details/80784908
今日推荐