计时器
计时器是一个应用程序的重要的一个组成部分,React Native 实现了Browser timers。
计时器
setTimeout,clearTimeout
setInterval, clearInterval
setImmediate, clearImmediate
requestAnimationFrame, cancelAnimationFrame
requestAnimationFrame(fn)
相当于setTimeout(fn, 0)
,他们是在刷新屏幕之后被正确触发。
setImmediate
是在向本地发送批处理相应之前,当前 JavaScript 执行块结束时执行的。注意,如果你在一个回调函数setImmediate
之内调用setImmediate
,它将立即被执行,而且不会返回到本地之间。
这个Promise
的实现是将setImmediate
作为异步性的开端。
交互管理器
良好的原生应用可以用起来感觉很顺利的一个原因是在交互和动画方面避免了复杂的操作。在 React Native,目前我们有一个限制,只有一个JS执行线程,但是你可以使用InteractionManager
来确保在任一交互或者动画完成之后,长期的运行工作的开始是被规划好的。
在下面的交互完成之后,应用程序可以安排任务来运行:
InteractionManager.runAfterInteractions(() => {
// ...long-running synchronous task...
});
与其他调度方案相比:
requestAnimationFrame():代码是在时间上的一个动画视图
setImmediate/setTimeout/setInterval():运行代码之后,请注意这可能会延迟动画
runAfterInteractions():运行代码之后,没有延迟的动态动画
触发处理系统将一个或多个触发看作是一个“交互”,并且将runAfterInteractions() 延迟回调,直到所有的触发都已结束或者被取消。
交互管理器还允许应用程序通过对动画的开始创建一个交互“处理”来注册动画,并且完成之后进行清理:
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
我们发现在 React Native 上的应用程序出现致命性问题的主要原因是由于一个组件被卸载后计时器就会被触发。为了解决这个反复出现的问题,我们引入了 TimerMixin。如果你有 TimerMixin,那么你可以用 this.setTimeout(fn, 500)(只是加上 this.)来替换 setTimeout(fn, 500) 函数的调用,并且当组件被卸载时,一切都会被清理干净。
这个库并没有跟着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
);
}
});
我们强烈建议不用只单独使用 Timers,而是一直使用 mixin,这样将会为你节省很多很难追踪的bugs。
我们强烈建议您使用react-timer-mixin提供的this.setTimeout(...)来代替setTimeout(...)。这可以规避许多难以排查的BUG。
译注:Mixin属于ES5语法,对于ES6代码来说,无法直接使用Mixin。如果你的项目是用ES6代码编写,同时又使用了计时器,那么你只需铭记在unmount组件时清除(clearTimeout/clearInterval)所有用到的定时器,那么也可以实现和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,那么用多个变量,或者用个数组来保存引用,然后逐个clear
this.timer && clearTimeout(this.timer);
}
};
例如
setTimeout(
() => {
const {navigator}=this.props;
if (navigator) {
navigator.popToRoute(navigator.getCurrentRoutes()[1])
}
},2000
);
网友评论