有没有一种方法可以保留对对象的引用而又不干扰它们的常规垃圾回收?

时间:2019-04-26 13:34:37

标签: javascript reference garbage-collection

我正在尝试为我的Javascript应用程序构建基于信号的系统,并且我有类似的东西:

class EventHubListener {
    constructor(eventName, callback, errorHandling) {
        this.eventName = eventName;
        this.callback = callback;
        this.errorHandling = errorHandling;
    }
}

class EventsHub {

    constructor() {
        this.listeners = [];
        this.idgen = 0;
        this.defaultErrorHandler = null;
    }

    registerListener(listenerInstance) {// EventHubListener
        this.listeners.push(listenerInstance);
        return listenerInstance.id = ++idgen;
    }

    register(eventName, callback, errorHandling) {
        return registerListener(new EventHubListener(eventName, callback, errorHandling));
    }

    watchRemoteChange(type, field, callback, handling) {
        return register('EvtRemoteStateChange', (data)=> {
            if(!data || data.ObjectType !== type || !data.ChangedObject)
                return;
            callback(data.changedObject.id, data.ChangedObject[field]);
        }, handling);
    }

    unregisterListener(id) {
        this.listeners = this.listeners.filter(i=> i.id != id);
    }

    raise(eventName, data) {
        this.listeners.forEach(l=> l.eventName === eventName, listener=> {
            try {
                if(listener.eventName === eventName)
                    listener.callback(data);
            } catch(err) {
                if(listener.errorHandling) {
                    try {
                        listener.errorHandling(err);
                    } catch(internalError) {
                        this.handleError(internalError);
                    }
                } else {
                    this.handleError(err);
                }
            }
        });
    }

    handleError(err) {
        if(this.defaultErrorHandler) {
            try {
                this.defaultErrorHandler(err);
            } catch(errorHandlingError) {
                console.trace('Error in the default error handling routine', err, errorHandlingError);
            }
        } else {
            throw internalError;
        }
    }
}

// use
hub.watchRemoteChange('Products', 'SellingPrice', (id, value)=> {
    console.writeLine(`Product ${id} has changed price to ${value}!`);
});

这里的问题是,我想这个“使用”示例将使Hub类持有对该匿名函数的引用:

(id, value)=> {
    console.writeLine(`Product ${id} has changed price to ${value}!`);
}

在此示例中,这似乎不是什么大问题,但它可能使用了闭包中的值,以防在收集用户类的情况下最终收集到这些值(我想是吗?),我这里需要的是一种方法要检测到用户类已被处置,并使集线器类停止持有它们或它们的闭包,并可能避免执行损坏的闭包,是否有办法在库侧做到这一点,或者我必须始终手动管理从中注销我的侦听器用户代码?

0 个答案:

没有答案