React-Native之定時(shí)器Timer的實(shí)現(xiàn)代碼
在web開發(fā)中,我們通常需要使用定時(shí)器功能,使用setTimeout和setInterval函數(shù)。
那么在ReactNative中,是否也提供了定時(shí)器的功能呢? 答案是肯定的。
我們還是先看看官網(wǎng)怎么說(shuō)的。
定時(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來(lái)執(zhí)行異步調(diào)用。
InteractionManager(交互管理器)
原生應(yīng)用感覺(jué)如此流暢的一個(gè)重要原因就是在互動(dòng)和動(dòng)畫的過(guò)程中避免繁重的操作。在React Native里,我們目前受到限制,因?yàn)槲覀冎挥幸粋€(gè)JavaScript執(zhí)行線程。不過(guò)你可以用InteractionManager來(lái)確保在執(zhí)行繁重工作之前所有的交互和動(dòng)畫都已經(jīng)處理完畢。
應(yīng)用可以通過(guò)以下代碼來(lái)安排一個(gè)任務(wù),使其在交互結(jié)束之后執(zhí)行:
InteractionManager.runAfterInteractions(() => {
// ...需要長(zhǎng)時(shí)間同步執(zhí)行的任務(wù)...
});
我們來(lái)把它和之前的幾個(gè)任務(wù)安排方法對(duì)比一下:
requestAnimationFrame(): 用來(lái)執(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)用注冊(cè)動(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)。具體來(lái)說(shuō),是在某個(gè)組件被卸載(unmount)之后,計(jì)時(shí)器卻仍然被激活。為了解決這個(gè)問(wèn)題,我們引入了TimerMixin。如果你在組件中引入TimerMixin,就可以把你原本的setTimeout(fn, 500)改為this.setTimeout(fn, 500)(只需要在前面加上this.),然后當(dāng)你的組件卸載時(shí),所有的計(jì)時(shí)器事件也會(huì)被正確的清除。
這個(gè)庫(kù)并沒(méi)有跟著React Native一起發(fā)布。你需要在項(xiàng)目文件夾下輸入npm i react-timer-mixin --save來(lái)單獨(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(...)來(lái)代替setTimeout(...)。這可以規(guī)避許多難以排查的BUG。
譯注:Mixin屬于ES5語(yǔ)法,對(duì)于ES6代碼來(lái)說(shuō),無(wú)法直接使用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ù)組來(lái)保存引用,然后逐個(gè)clear
this.timer && clearTimeout(this.timer);
}
};
注意點(diǎn):
1、定時(shí)器功能比較簡(jiǎn)單,注意在es6中使用時(shí),需銘記在unmount組件時(shí)清除(clearTimeout/clearInterval)所有用到的定時(shí)器。
2、可以使用定時(shí)器實(shí)現(xiàn)一些普通功能:如短信倒計(jì)時(shí)等
3、對(duì)于一些需要延遲執(zhí)行的特殊場(chǎng)景也可以使用Timer,譬如:目前RN提供的fetch是沒(méi)有提供設(shè)置超時(shí)時(shí)間的,如果客戶端請(qǐng)求后端的一個(gè)接口,接口超時(shí)了(后端服務(wù)設(shè)置的超時(shí)時(shí)間為10s),那么RN界面就一直loading,也不能aborded。那么這時(shí)候我們就可以巧妙的使用計(jì)時(shí)器,如果客戶端發(fā)出的Request,時(shí)間大于某個(gè)值(5秒),那么我們直接認(rèn)為請(qǐng)求失敗。
4、今天還發(fā)現(xiàn)一個(gè)使用setTimeout的場(chǎng)景,在列表頁(yè)加載下一頁(yè)的時(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
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
使用react-native-image-viewer實(shí)現(xiàn)大圖預(yù)覽
這篇文章主要介紹了使用react-native-image-viewer實(shí)現(xiàn)大圖預(yù)覽,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
React中的權(quán)限組件設(shè)計(jì)問(wèn)題小結(jié)
這篇文章主要介紹了React中的權(quán)限組件設(shè)計(jì),整個(gè)過(guò)程也是遇到了很多問(wèn)題,本文主要來(lái)做一下此次改造工作的總結(jié),對(duì)React權(quán)限組件相關(guān)知識(shí)感興趣的朋友一起看看吧2022-07-07
React Js 微信禁止復(fù)制鏈接分享禁止隱藏右上角菜單功能
這篇文章主要介紹了React Js 微信禁止復(fù)制鏈接,分享,禁止隱藏右上角菜單的解決代碼,需要的朋友可以參考下2017-05-05
React+Ant Design開發(fā)環(huán)境搭建的實(shí)現(xiàn)步驟
這篇文章主要介紹了React+Ant Design開發(fā)環(huán)境搭建的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
react使用useImperativeHandle示例詳解
這篇文章主要為大家介紹了react使用useImperativeHandle示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09

