計(jì)時器
計(jì)時器是一個應(yīng)用程序的重要的一個組成部分欣福,React Native 實(shí)現(xiàn)了Browser timers弧可。
計(jì)時器
setTimeout,clearTimeout
setInterval, clearInterval
setImmediate, clearImmediate
requestAnimationFrame, cancelAnimationFrame
requestAnimationFrame(fn)
相當(dāng)于setTimeout(fn, 0)
,他們是在刷新屏幕之后被正確觸發(fā)劣欢。
setImmediate
是在向本地發(fā)送批處理相應(yīng)之前棕诵,當(dāng)前 JavaScript 執(zhí)行塊結(jié)束時執(zhí)行的。注意凿将,如果你在一個回調(diào)函數(shù)setImmediate
之內(nèi)調(diào)用setImmediate
校套,它將立即被執(zhí)行,而且不會返回到本地之間牧抵。
這個Promise
的實(shí)現(xiàn)是將setImmediate
作為異步性的開端笛匙。
交互管理器
良好的原生應(yīng)用可以用起來感覺很順利的一個原因是在交互和動畫方面避免了復(fù)雜的操作。在 React Native犀变,目前我們有一個限制妹孙,只有一個JS執(zhí)行線程,但是你可以使用InteractionManager
來確保在任一交互或者動畫完成之后获枝,長期的運(yùn)行工作的開始是被規(guī)劃好的蠢正。
在下面的交互完成之后,應(yīng)用程序可以安排任務(wù)來運(yùn)行:
InteractionManager.runAfterInteractions(() => {
// ...long-running synchronous task...
});
與其他調(diào)度方案相比:
requestAnimationFrame():代碼是在時間上的一個動畫視圖
setImmediate/setTimeout/setInterval():運(yùn)行代碼之后省店,請注意這可能會延遲動畫
runAfterInteractions():運(yùn)行代碼之后嚣崭,沒有延遲的動態(tài)動畫
觸發(fā)處理系統(tǒng)將一個或多個觸發(fā)看作是一個“交互”,并且將runAfterInteractions() 延遲回調(diào)懦傍,直到所有的觸發(fā)都已結(jié)束或者被取消雹舀。
交互管理器還允許應(yīng)用程序通過對動畫的開始創(chuàng)建一個交互“處理”來注冊動畫,并且完成之后進(jìn)行清理:
var handle = InteractionManager.createInteractionHandle();
// run animation... (`runAfterInteractions` tasks are queued)
// later, on animation completion:
InteractionManager.clearInteractionHandle(handle);
// queued tasks run if all handles were cleared
TimerMixin
我們發(fā)現(xiàn)在 React Native 上的應(yīng)用程序出現(xiàn)致命性問題的主要原因是由于一個組件被卸載后計(jì)時器就會被觸發(fā)粗俱。為了解決這個反復(fù)出現(xiàn)的問題说榆,我們引入了 TimerMixin。如果你有 TimerMixin,那么你可以用 this.setTimeout(fn, 500)(只是加上 this.)來替換 setTimeout(fn, 500) 函數(shù)的調(diào)用签财,并且當(dāng)組件被卸載時稍味,一切都會被清理干凈。
這個庫并沒有跟著React Native一起發(fā)布荠卷。你需要在項(xiàng)目文件夾下輸入npm i react-timer-mixin --save來單獨(dú)安裝它模庐。
var TimerMixin = require('react-timer-mixin');
var Component = React.createClass({
mixins: [TimerMixin],
componentDidMount: function() {
this.setTimeout(
() => { console.log('這樣我就不會導(dǎo)致內(nèi)存泄露!'); },
500
);
}
});
我們強(qiáng)烈建議不用只單獨(dú)使用 Timers,而是一直使用 mixin油宜,這樣將會為你節(jié)省很多很難追蹤的bugs掂碱。
我們強(qiáng)烈建議您使用react-timer-mixin提供的this.setTimeout(...)來代替setTimeout(...)。這可以規(guī)避許多難以排查的BUG慎冤。
譯注:Mixin屬于ES5語法疼燥,對于ES6代碼來說,無法直接使用Mixin蚁堤。如果你的項(xiàng)目是用ES6代碼編寫醉者,同時又使用了計(jì)時器,那么你只需銘記在unmount組件時清除(clearTimeout/clearInterval)所有用到的定時器披诗,那么也可以實(shí)現(xiàn)和TimerMixin同樣的效果撬即。例如:
import React,{
Component
} from 'react';
export default class Hello extends Component {
componentDidMount() {
this.timer = setTimeout(
() => { console.log('把一個定時器的引用掛在this上'); },
500
);
}
componentWillUnmount() {
// 如果存在this.timer,則使用clearTimeout清空呈队。
// 如果你使用多個timer剥槐,那么用多個變量,或者用個數(shù)組來保存引用宪摧,然后逐個clear
this.timer && clearTimeout(this.timer);
}
};
例如
setTimeout(
() => {
const {navigator}=this.props;
if (navigator) {
navigator.popToRoute(navigator.getCurrentRoutes()[1])
}
},2000
);