React-Native之定時(shí)器Timer的實(shí)現(xiàn)代碼
在web開發(fā)中,我們通常需要使用定時(shí)器功能,使用setTimeout和setInterval函數(shù)。
那么在ReactNative中,是否也提供了定時(shí)器的功能呢? 答案是肯定的。
我們還是先看看官網(wǎng)怎么說的。
定時(shí)器是一個(gè)應(yīng)用中非常重要的部分。React Native實(shí)現(xiàn)了和瀏覽器一致的定時(shí)器Timer。
提供的方法如下:
- setTimeout, clearTimeout
- setInterval, clearInterval
- setImmediate, clearImmediate
- requestAnimationFrame, cancelAnimationFrame
setTimeout (fn, 1000) 和 setInterval (fn,1000)
和web中的意思一樣,前者表示延遲1000毫秒后執(zhí)行 fn 方法 ,后者表示每隔1000毫秒執(zhí)行 fn 方法。
requestAnimationFrame(fn)和setTimeout(fn, 0)不同,前者會(huì)在每幀刷新之后執(zhí)行一次,而后者則會(huì)盡可能快的執(zhí)行(在iPhone5S上有可能每秒1000次以上)。
setImmediate則會(huì)在當(dāng)前JavaScript執(zhí)行塊結(jié)束的時(shí)候執(zhí)行,就在將要發(fā)送批量響應(yīng)數(shù)據(jù)到原生之前。注意如果你在setImmediate的回調(diào)函數(shù)中又執(zhí)行了setImmediate,它會(huì)緊接著立刻執(zhí)行,而不會(huì)在調(diào)用之前等待原生代碼。
Promise的實(shí)現(xiàn)就使用了setImmediate來執(zhí)行異步調(diào)用。
InteractionManager(交互管理器)
原生應(yīng)用感覺如此流暢的一個(gè)重要原因就是在互動(dòng)和動(dòng)畫的過程中避免繁重的操作。在React Native里,我們目前受到限制,因?yàn)槲覀冎挥幸粋€(gè)JavaScript執(zhí)行線程。不過你可以用InteractionManager來確保在執(zhí)行繁重工作之前所有的交互和動(dòng)畫都已經(jīng)處理完畢。
應(yīng)用可以通過以下代碼來安排一個(gè)任務(wù),使其在交互結(jié)束之后執(zhí)行:
InteractionManager.runAfterInteractions(() => {
// ...需要長時(shí)間同步執(zhí)行的任務(wù)...
});
我們來把它和之前的幾個(gè)任務(wù)安排方法對比一下:
requestAnimationFrame(): 用來執(zhí)行在一段時(shí)間內(nèi)控制視圖動(dòng)畫的代碼
setImmediate/setTimeout/setInterval(): 在稍后執(zhí)行代碼。注意這有可能會(huì)延遲當(dāng)前正在進(jìn)行的動(dòng)畫。
runAfterInteractions(): 在稍后執(zhí)行代碼,不會(huì)延遲當(dāng)前進(jìn)行的動(dòng)畫。
觸摸處理系統(tǒng)會(huì)把一個(gè)或多個(gè)進(jìn)行中的觸摸操作認(rèn)定為'交互',并且會(huì)將runAfterInteractions()的回調(diào)函數(shù)延遲執(zhí)行,直到所有的觸摸操作都結(jié)束或取消了。
InteractionManager還允許應(yīng)用注冊動(dòng)畫,在動(dòng)畫開始時(shí)創(chuàng)建一個(gè)交互“句柄”,然后在結(jié)束的時(shí)候清除它。
var handle = InteractionManager.createInteractionHandle(); // 執(zhí)行動(dòng)畫... (`runAfterInteractions`中的任務(wù)現(xiàn)在開始排隊(duì)等候) // 在動(dòng)畫完成之后 InteractionManager.clearInteractionHandle(handle); // 在所有句柄都清除之后,現(xiàn)在開始依序執(zhí)行隊(duì)列中的任務(wù)
TimerMixin
我們發(fā)現(xiàn)很多React Native應(yīng)用發(fā)生致命錯(cuò)誤(閃退)是與計(jì)時(shí)器有關(guān)。具體來說,是在某個(gè)組件被卸載(unmount)之后,計(jì)時(shí)器卻仍然被激活。為了解決這個(gè)問題,我們引入了TimerMixin。如果你在組件中引入TimerMixin,就可以把你原本的setTimeout(fn, 500)改為this.setTimeout(fn, 500)(只需要在前面加上this.),然后當(dāng)你的組件卸載時(shí),所有的計(jì)時(shí)器事件也會(huì)被正確的清除。
這個(gè)庫并沒有跟著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('這樣我就不會(huì)導(dǎo)致內(nèi)存泄露!'); },
500
);
}
});
我們強(qiáng)烈建議您使用react-timer-mixin提供的this.setTimeout(...)來代替setTimeout(...)。這可以規(guī)避許多難以排查的BUG。
譯注:Mixin屬于ES5語法,對于ES6代碼來說,無法直接使用Mixin。
如果你的項(xiàng)目是用ES6代碼編寫,同時(shí)又使用了計(jì)時(shí)器,那么你只需銘記在unmount組件時(shí)清除(clearTimeout/clearInterval)所有用到的定時(shí)器。
那么也可以實(shí)現(xiàn)和TimerMixin同樣的效果。例如:
import React,{
Component
} from 'react-native';
export default class Hello extends Component {
componentDidMount() {
this.timer = setTimeout(
() => { console.log('把一個(gè)定時(shí)器的引用掛在this上'); },
500
);
}
componentWillUnmount() {
// 如果存在this.timer,則使用clearTimeout清空。
// 如果你使用多個(gè)timer,那么用多個(gè)變量,或者用個(gè)數(shù)組來保存引用,然后逐個(gè)clear
this.timer && clearTimeout(this.timer);
}
};
注意點(diǎn):
1、定時(shí)器功能比較簡單,注意在es6中使用時(shí),需銘記在unmount組件時(shí)清除(clearTimeout/clearInterval)所有用到的定時(shí)器。
2、可以使用定時(shí)器實(shí)現(xiàn)一些普通功能:如短信倒計(jì)時(shí)等
3、對于一些需要延遲執(zhí)行的特殊場景也可以使用Timer,譬如:目前RN提供的fetch是沒有提供設(shè)置超時(shí)時(shí)間的,如果客戶端請求后端的一個(gè)接口,接口超時(shí)了(后端服務(wù)設(shè)置的超時(shí)時(shí)間為10s),那么RN界面就一直loading,也不能aborded。那么這時(shí)候我們就可以巧妙的使用計(jì)時(shí)器,如果客戶端發(fā)出的Request,時(shí)間大于某個(gè)值(5秒),那么我們直接認(rèn)為請求失敗。
4、今天還發(fā)現(xiàn)一個(gè)使用setTimeout的場景,在列表頁加載下一頁的時(shí)候,如果接口響應(yīng)很快,就不會(huì)出現(xiàn)loading的效果,這個(gè)時(shí)候?yàn)榱擞衛(wèi)oading的效果,設(shè)置一個(gè)500毫秒的延時(shí),呵呵....
參考:http://reactnative.cn/docs/0.31/timers.html#content
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
react中關(guān)于Context/Provider/Consumer傳參的使用
這篇文章主要介紹了react中關(guān)于Context/Provider/Consumer傳參的使用,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
react-native滑動(dòng)吸頂效果的實(shí)現(xiàn)過程
這篇文章主要給大家介紹了關(guān)于react-native滑動(dòng)吸頂效果的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用react-native具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
詳解使用React.memo()來優(yōu)化函數(shù)組件的性能
本文講述了開發(fā)React應(yīng)用時(shí)如何使用shouldComponentUpdate生命周期函數(shù)以及PureComponent去避免類組件進(jìn)行無用的重渲染,以及如何使用最新的React.memo API去優(yōu)化函數(shù)組件的性能2019-03-03
React實(shí)現(xiàn)雙滑塊交叉滑動(dòng)
這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)雙滑塊交叉滑動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
useEffect?返回函數(shù)執(zhí)行過程源碼解析
這篇文章主要為大家介紹了useEffect?返回函數(shù)執(zhí)行過程源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04

