react-native定时任务

react-native中有时候需要定时执行一些后台任务,比如定时发送消息,定时统计数据等.这个时候就需要使用另外注册一个视图来做这些东西了,不然在同步任务中做这些任务,一旦任务比较耗时就会卡住后面的进程,甚至导致后面的进程不再渲染页面.

注册另外一个入口

在合适的位置:页面启动或者某个需要的时候,注册并启动我们的另外一个视图.这个时候其实相当于启动了另外一个线程.

这里注意一下,这个视图里的东西千万不要直接刷新UI相关的数据,所有的内容都应该是内存相关的.

AppRegistry.registerRunnable('RunableTask', TaskRun)

AppRegistry.runApplication('RunableTask', {});
复制代码

启动定时器

调用init方法,启动我们自己的定时器刷新方法,这里我暂时定义1秒刷新一次,低于1秒间隔的定时器将不在执行.这里也是为了防止部分人设置低间隔的定时器导致APP崩溃.

这里使用react-native内部提供的requestAnimationFrame方法,每次刷新的时候先判断一次是否可以执行任务.

const tasks = new Map();
let currDate = Date.now();
/**
 * 初始化
 */
exports.init = function () {
    global.requestAnimationFrame(run);
}
/**
 * 执行,每秒执行一次
 * 保证秒级工作正确
 */
function run() {
    const now = Date.now();
    if (now > currDate + 1000) {
        currDate = now;
        tasks.forEach(item => item.preStart(now));
    }
    global.requestAnimationFrame(run);
}
复制代码

任务基类

所有的任务都需要继承这个基类,定时器运行的时候也会通过基类内部的方法去判断是否需要执行方法.这里对外实现了一个timer是时间间隔,单位是毫秒,还有一个start方法用来给每个任务使用的.

通过每次执行preStart方法判断下次执行的时间到了没有来决定是否执行自定义方法.如果到了同时还要计算下一次的时间并存好.

/**
 * 基础工作类
 */
class Jobs {
    name = "base";
    /**
     * 下次执行时间戳
     */
    nextTime = 0;
    /**
     * 重载:时间间隔
     */
    timer = 0;
    /**
     * 预启动
     */
    preStart(now) {
        if (this.timer < 1000) return;
        if (this.nextTime > now) return;
        if (this.nextTime === 0) return this.nextTime = now + this.timer;
        this.nextTime += this.timer;
        this.start(now);
    }
    /**
     * 重载:执行一次设置的方法
     */
    start() { }
}
复制代码

实现并加入

将设置好的任务加入全局的map示例中,运行的时候会从这个示例中取需要的任务出来.

/**
 * 添加一个工作
 * @param {*} name  名称
 * @param {*} time  时间
 * @param {*} fn    执行函数
 */
const addJob = (name, Job) => tasks.set(name, new Job())

exports.addJob = addJob;

/**
 * 取消任务
 * @param {*} name 
 */
const cancelJob = name => tasks.delete(name);

exports.cancelJob = cancelJob;
复制代码

测试任务

这里模拟一次定时发送统计消息.

另外一个地方实现了将每次需要发送的消息存入内存中,这里只负责取出需要发送的消息.

设置3秒执行一次发送任务,如果数量比较少就修改定时任务的间隔,后面的任务延迟发送.

如果后台接收一次大量的数据,也可以将多次统计合并为一次统计,请求的个数会更少一些.

/**
 * 定时触发统计方法
 */
class TrackJob extends Jobs {
    timer = 3000;
    start() {
        let list = TackList();
        if (list.length > 10) {
            this.timer = 3000;
        } else {
            this.timer = 5000;
        }
        list.forEach(item => {
            request.trackData(item.url, item.data);
            log("埋点事件", item.data);
        })
    }
}
addJob("Track", TrackJob);
复制代码

更多扩展

在目前的基础上扩展时间间隔的设定方式,实现固定时间日期执行任务.这里可能需要app一直活着才能保证.

加入执行次数,执行超过一定的此时就不再执行.

文章地址


作者:疯狂紫萧2018
链接:https://juejin.im/post/5af66a0f6fb9a07aae153fea
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值