Node.js教程之用Node.js实现延迟调用规避定时任务的闭包问题
沉沙 2019-04-15 来源 : 阅读 1160 评论 0

摘要:本篇文章探讨了Node.js教程之用Node.js实现延迟调用规避定时任务的闭包问题,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

本篇文章探讨了Node.js教程之用Node.js实现延迟调用规避定时任务的闭包问题,希望阅读本篇文章以后大家有所收获,帮助大家对相关内容的理解更加深入。

Node.js教程之用Node.js实现延迟调用规避定时任务的闭包问题

<

 很多人在用NodeJs的setTimeout(callback, delay[, arg][, ...])编写定时任务时,习惯上直接操作callback外部的对象object(闭包的特点)。这样做有一个隐患,就是当callback真正执行的时候,外部对象object可能已经被销毁了(比如执行了自定义的销毁方法),导致对object进行的处理结果出现了很大的偏差,程序甚至有可能出现异常而退出。
解决这个问题其实很简单,我们只需要在callback回调中重新通过某种方式获取该对象,检查一下该对象是否已被销毁,即可避免上面描述的问题。但是,当程序中需要很多这样的需求时,并且是一个团队在合作写代码,这样就很难避免上述情况的发生。为了规避定时任务的闭包问题,我写了一个延迟调用类,代码如下:
/**
 * script: delayCall.js
 * description: 延迟调用,规避定时任务的闭包问题
 * authors: alwu007@sina.cn
 * date: 2016-04-19
 */
var util = require(‘util‘);
var PQueue = require(‘./pqueue‘).PQueue;
/**
 * 延迟调用类
 * @param search_func 对象查找函数
 */
var DelayCall = exports.DelayCall = function(search_func) {
    //延迟调用序号
    this._call_seq = 0;
    //延迟调用映射
    this._call_map = {};
    //延迟调用队列
    this._call_queue = new PQueue(DelayCall.compare);
    //对象查找方法
    this._search_func = search_func;
    //设置间隔定时器。FIXME:可以改为在框架的心跳机制中去执行run方法
    //注:setTimeout不支持修改系统时间
    this._interval_id = setInterval(() => {
        this.run();
    }, 1000);
};
//比较延迟调用
DelayCall.compare = function(call1, call2) {
    var time_diff = call1.exec_time - call2.exec_time;
    if (time_diff) {
        return time_diff;
    } else {
        return call1._call_id - call2._call_id;
    }
};
//延迟调用序号自增
DelayCall.prototype._addSequence = function() {
    return ++ this._call_seq;
};
/**
 * 延迟调用
 * @param id 对象查找方法_search_func根据id查找出调用者对象
 * @param method_name 调用者对象上要延迟调用的方法名
 * @param params 要延迟调用的方法参数
 * @param delay 延迟时间,单位秒
 */
DelayCall.prototype.call = function(id, method_name, params, delay) {
    var call_id = this._addSequence();
    var exec_time = Date.now() + delay * 1000;
    var call_elem = {
        _call_id: call_id,
        id: id,
        method_name: method_name,
        params: params,
        delay: delay,
        exec_time: exec_time,
        _canceled: false,
    };
    this._call_queue.enQueue(call_elem);
    this._call_map[call_id] = call_elem;
    return call_id;
};
//取消延迟调用
DelayCall.prototype.cancelCall = function(call_id) {
    var call_elem = this._call_map[call_id];
    if (call_elem) {
        delete this._call_map[call_id];
        call_elem._canceled = true;
    }
};
//运转一次
DelayCall.prototype.run = function() {
    var now = Date.now();
    var pqueue = this._call_queue;
    var search_func = this._search_func;
    var call_elem = pqueue.getHead();
    while (call_elem) {
        if (call_elem._canceled) {
            pqueue.deQueue();
        } else {
            if (now < call_elem.exec_time) {
                break;
            } else {
                //从队列和映射中删除
                pqueue.deQueue();
                delete this._call_map[call_elem._call_id];
                //执行对象的方法
                var obj = search_func(call_elem.id);
                if (obj && typeof obj[call_elem.method_name] == ‘function‘) {
                    obj[call_elem.method_name](call_elem.params);
                }
            }
        }
        call_elem = pqueue.getHead();
    }
};
   

      本文由职坐标整理发布,学习更多的相关知识,请关注职坐标IT知识库!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程