NodeJs 로 지연 호출 을 실현 하여 정시 작업 의 폐쇄 문 제 를 회피 합 니 다.

3877 단어
많은 사람들 이 NodeJs 의 setTimeout (callback, delay [, arg] [,...]) 으로 정시 작업 을 작성 할 때, 습관 적 으로 callback 외부의 대상 object (패 킷 을 닫 는 특징) 를 직접 조작 합 니 다.이렇게 하면 하나의 위험 이 있 습 니 다. 바로 callback 이 진정 으로 실 행 될 때 외부 대상 object 가 이미 소각 되 었 을 수도 있 습 니 다 (예 를 들 어 사용자 정의 소각 방법 을 실 행 했 습 니 다). 그래서 object 에 대한 처리 결과 에 큰 오차 가 생 겼 고 프로그램 에 이상 이 생 겨 서 종료 할 수도 있 습 니 다.
이 문 제 를 해결 하 는 것 은 매우 간단 하 다. 우 리 는 콜백 리 셋 에서 이 대상 을 다시 어떤 방식 으로 얻 고 이 대상 이 이미 소각 되 었 는 지 확인 하면 위 에서 설명 한 문 제 를 피 할 수 있다.그러나 프로그램 에 이러한 수요 가 많이 필요 할 때 한 팀 이 코드 를 작성 하면 상기 상황 을 피하 기 어렵다.정시 작업 의 폐쇄 문 제 를 피하 기 위해 저 는 지연 호출 클래스 를 썼 습 니 다. 코드 는 다음 과 같 습 니 다.
/**
 * script: delayCall.js
 * description:     ,           
 * authors: [email protected]
 * 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();
    }
};

 PQueue 의 실현 은 나의 배 고 픈 다른 박문 을 참고 하 세 요: NodeJs 로 우선 순위 대기 열 PQueue 를 실현 합 니 다.

좋은 웹페이지 즐겨찾기