做惯了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可以标记多个异步请求,简单方便,可以说是完美解决问题,墙裂推荐!