Есть ли способ хранить ссылки на объекты, не мешая их обычной сборке мусора? - PullRequest
0 голосов
/ 26 апреля 2019

Я пытаюсь создать систему на основе сигналов для моего приложения 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}!`);
}

Что в этом примере не кажется большой проблемой, но это может быть использование значений из замыкания, которые в конечном итоге будут собираться в случае сбора пользовательского класса (я полагаю?), Здесь мне нужен способ чтобы обнаружить, что пользовательский класс был удален, и заставить хаб-класс перестать удерживать их или их замыкания и, возможно, избежать выполнения нарушенных замыканий, есть ли способ сделать это на стороне библиотеки, или мне всегда нужно вручную управлять отменой регистрации слушателей из код пользователя?

...