React-Native之定时器Timer的实现代码


Posted in Javascript onOctober 04, 2017

在web开发中,我们通常需要使用定时器功能,使用setTimeout和setInterval函数。

那么在ReactNative中,是否也提供了定时器的功能呢? 答案是肯定的。

我们还是先看看官网怎么说的。

定时器是一个应用中非常重要的部分。React Native实现了和浏览器一致的定时器Timer。

提供的方法如下:

  • setTimeout, clearTimeout
  • setInterval, clearInterval
  • setImmediate, clearImmediate
  • requestAnimationFrame, cancelAnimationFrame

setTimeout (fn, 1000)  和 setInterval (fn,1000)

和web中的意思一样,前者表示延迟1000毫秒后执行 fn 方法 ,后者表示每隔1000毫秒执行 fn 方法。

requestAnimationFrame(fn)和setTimeout(fn, 0)不同,前者会在每帧刷新之后执行一次,而后者则会尽可能快的执行(在iPhone5S上有可能每秒1000次以上)。

setImmediate则会在当前JavaScript执行块结束的时候执行,就在将要发送批量响应数据到原生之前。注意如果你在setImmediate的回调函数中又执行了setImmediate,它会紧接着立刻执行,而不会在调用之前等待原生代码。

Promise的实现就使用了setImmediate来执行异步调用。

InteractionManager(交互管理器)

原生应用感觉如此流畅的一个重要原因就是在互动和动画的过程中避免繁重的操作。在React Native里,我们目前受到限制,因为我们只有一个JavaScript执行线程。不过你可以用InteractionManager来确保在执行繁重工作之前所有的交互和动画都已经处理完毕。

应用可以通过以下代码来安排一个任务,使其在交互结束之后执行:

InteractionManager.runAfterInteractions(() => { 
  // ...需要长时间同步执行的任务... 
});

我们来把它和之前的几个任务安排方法对比一下:

requestAnimationFrame(): 用来执行在一段时间内控制视图动画的代码

setImmediate/setTimeout/setInterval(): 在稍后执行代码。注意这有可能会延迟当前正在进行的动画。

runAfterInteractions(): 在稍后执行代码,不会延迟当前进行的动画。
触摸处理系统会把一个或多个进行中的触摸操作认定为'交互',并且会将runAfterInteractions()的回调函数延迟执行,直到所有的触摸操作都结束或取消了。

InteractionManager还允许应用注册动画,在动画开始时创建一个交互“句柄”,然后在结束的时候清除它。

var handle = InteractionManager.createInteractionHandle(); 
// 执行动画... (`runAfterInteractions`中的任务现在开始排队等候) 
// 在动画完成之后 
InteractionManager.clearInteractionHandle(handle); 
// 在所有句柄都清除之后,现在开始依序执行队列中的任务

TimerMixin

我们发现很多React Native应用发生致命错误(闪退)是与计时器有关。具体来说,是在某个组件被卸载(unmount)之后,计时器却仍然被激活。为了解决这个问题,我们引入了TimerMixin。如果你在组件中引入TimerMixin,就可以把你原本的setTimeout(fn, 500)改为this.setTimeout(fn, 500)(只需要在前面加上this.),然后当你的组件卸载时,所有的计时器事件也会被正确的清除。

这个库并没有跟着React Native一起发布。你需要在项目文件夹下输入npm i react-timer-mixin --save来单独安装它。

var TimerMixin = require('react-timer-mixin'); 
 
var Component = React.createClass({ 
 mixins: [TimerMixin], 
 componentDidMount: function() { 
  this.setTimeout( 
   () => { console.log('这样我就不会导致内存泄露!'); }, 
   500 
  ); 
 } 
});

我们强烈建议您使用react-timer-mixin提供的this.setTimeout(...)来代替setTimeout(...)。这可以规避许多难以排查的BUG。

译注:Mixin属于ES5语法,对于ES6代码来说,无法直接使用Mixin。

如果你的项目是用ES6代码编写,同时又使用了计时器,那么你只需铭记在unmount组件时清除(clearTimeout/clearInterval)所有用到的定时器。

那么也可以实现和TimerMixin同样的效果。例如:

import React,{ 
 Component 
} from 'react-native'; 
 
 
export default class Hello extends Component { 
 componentDidMount() { 
  this.timer = setTimeout( 
   () => { console.log('把一个定时器的引用挂在this上'); }, 
   500 
  ); 
 } 
 componentWillUnmount() { 
  // 如果存在this.timer,则使用clearTimeout清空。 
  // 如果你使用多个timer,那么用多个变量,或者用个数组来保存引用,然后逐个clear 
  this.timer && clearTimeout(this.timer); 
 } 
};

注意点:

1、定时器功能比较简单,注意在es6中使用时,需铭记在unmount组件时清除(clearTimeout/clearInterval)所有用到的定时器。
2、可以使用定时器实现一些普通功能:如短信倒计时等
3、对于一些需要延迟执行的特殊场景也可以使用Timer,譬如:目前RN提供的fetch是没有提供设置超时时间的,如果客户端请求后端的一个接口,接口超时了(后端服务设置的超时时间为10s),那么RN界面就一直loading,也不能aborded。那么这时候我们就可以巧妙的使用计时器,如果客户端发出的Request,时间大于某个值(5秒),那么我们直接认为请求失败。
4、今天还发现一个使用setTimeout的场景,在列表页加载下一页的时候,如果接口响应很快,就不会出现loading的效果,这个时候为了有loading的效果,设置一个500毫秒的延时,呵呵....

参考:http://reactnative.cn/docs/0.31/timers.html#content

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery复选框CHECKBOX全选、反选
Aug 30 Javascript
event.srcElement 用法笔记e.target
Dec 18 Javascript
淘宝搜索框效果实现分析
Mar 05 Javascript
jQuery选择器源码解读(八):addCombinator函数
Mar 31 Javascript
JavaScript trim 实现去除字符串首尾指定字符的简单方法
Dec 27 Javascript
JavaScript函数柯里化原理与用法分析
Mar 31 Javascript
js 实现在2d平面上画8的方法
Oct 10 Javascript
Layui 数据表格批量删除和多条件搜索的实例
Sep 04 Javascript
微信小程序左滑删除实现代码实例
Sep 16 Javascript
Vue+Node实现的商城用户管理功能示例
Dec 23 Javascript
微信小程序点击滚动到指定位置的实现
May 22 Javascript
JavaScript 空间坐标的使用
Aug 19 Javascript
vuejs使用$emit和$on进行组件之间的传值的示例
Oct 04 #Javascript
无限循环轮播图之运动框架(原生JS实现)
Oct 01 #Javascript
原生JS实现图片无缝滚动方法(附带封装的运动框架)
Oct 01 #Javascript
原生js封装运动框架的示例讲解
Oct 01 #Javascript
JS Testing Properties 判断属性是否在对象里的方法
Oct 01 #Javascript
基于原生js运动方式关键点的总结(推荐)
Oct 01 #Javascript
vuejs使用递归组件实现树形目录的方法
Sep 30 #Javascript
You might like
PHP脚本的10个技巧(2)
2006/10/09 PHP
PHP使用curl模拟post上传及接收文件的方法
2016/03/04 PHP
CI框架中$this->load->library()用法分析
2016/05/18 PHP
Yii框架实现邮箱激活的方法【数字签名】
2016/10/18 PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
2017/11/17 PHP
javascript 中对象的继承〔转贴〕
2007/01/22 Javascript
QQ邮箱的一个文本编辑器代码
2007/03/14 Javascript
javascript函数库-集合框架
2007/04/27 Javascript
javascript 清除输入框中的数据
2009/04/13 Javascript
深入理解JavaScript系列(2) 揭秘命名函数表达式
2012/01/15 Javascript
深入理解JavaScript系列(13) This? Yes,this!
2012/01/18 Javascript
json字符串之间的相互转换示例代码
2014/08/21 Javascript
JavaScript 学习笔记之基础中的基础
2015/01/13 Javascript
Javascript中call和apply函数的比较和使用实例
2015/02/03 Javascript
全面解析JavaScript中“&&”和“||”操作符(总结篇)
2016/07/18 Javascript
详解Angular-Cli中引用第三方库
2017/05/21 Javascript
关于定制FileField中的上传文件名称问题
2017/08/22 Javascript
vue-devtools的安装步骤
2018/04/23 Javascript
使用Vue-cli 3.0搭建Vue项目的方法
2018/06/07 Javascript
JavaScript动态检测密码强度原理及实现方法详解
2019/06/11 Javascript
[01:28:56]2014 DOTA2华西杯精英邀请赛 5 24 CIS VS DK
2014/05/26 DOTA
[01:45]亚洲邀请赛互动指南虚拟物品介绍
2015/01/30 DOTA
Python 变量类型及命名规则介绍
2013/06/08 Python
wxpython学习笔记(推荐查看)
2014/06/09 Python
Python专用方法与迭代机制实例分析
2014/09/15 Python
使用python将图片按标签分入不同文件夹的方法
2018/12/08 Python
python编写猜数字小游戏
2019/10/06 Python
用python中的matplotlib绘制方程图像代码
2019/11/21 Python
使用Python的Turtle绘制哆啦A梦实例
2019/11/21 Python
python爬虫基础知识点整理
2020/06/02 Python
美国女性运动零售品牌:Lady Foot Locker
2017/05/12 全球购物
趣天网日本站:Qoo10 JP
2019/09/18 全球购物
小学生自我评价范例
2013/09/24 职场文书
学习雷锋活动总结
2014/04/29 职场文书
应届生求职信范文
2014/06/30 职场文书
民主生活会发言材料
2014/10/20 职场文书