Как я могу узнать, есть ли какие-либо ссылки на данный экземпляр?

#javascript #weak-references

Вопрос:

Я создаю очередь, и если нет ссылок на этот экземпляр очереди, я хочу избежать выполнения каких-либо задач.

Я пробовал кое WeakRef -что, но, вероятно, это никогда не сработает.

 const queue = () => {
  const enqueue = () => {
    console.log("enqueue");
    setTimeout(() => {
      if (instanceRef.deref()) {
        console.log("the queue is still referenced so perform task");
      }
    });
  };

  const instance = { enqueue };
  const instanceRef = new WeakRef(instance);
  return instance;
};
b = queue();
b.enqueue();
b = null;
console.log("b is set to null so there are no references to the instance"); 

Альтернативой было бы проверить задачи, если очередь все еще существует, но она менее элегантна.

Комментарии:

1. » вероятно, никогда не сработает » — почему бы и нет? Конечно, такой подход сработает, вы просто никогда не ждете достаточно долго instance , чтобы на самом деле был собран мусор.

2. Ну, наверное, никогда не работает надежно. Как долго вы ожидали бы ждать? Я подождал 1 минуту, на меня все еще ссылались.

3. Если он когда-нибудь решит собирать мусор… как, например, сейчас, отладчик, вероятно, все еще может использовать instance ссылку внутри закрытия, даже если она не используется внутри закрытия функции.

4. Ваш код на самом деле работает нормально, если вы перейдете на панель памяти devtools и нажмете кнопку » Собрать мусор » до истечения времени ожидания. Если вы хотите, чтобы это произошло само по себе, вам нужно будет оказать некоторое давление на память двигателя. Сборщик мусора не восстановит память, если вы не дадите ему повод для этого — просто ждать недостаточно. И даже в этом случае ваш код никогда не должен полагаться на сбор мусора. Если вы хотите, чтобы выполнение вашей задачи было детерминированным, вам нужно самостоятельно выполнить подсчет ссылок.

5. Потрясающе, спасибо Берги!

Ответ №1:

Нельзя полагаться на WeakRef#deref() то, чтобы знать, есть ли еще (сильные) ссылки на целевой объект. Он просто указывает, уничтожил ли сборщик мусора объект и восстановил ли его память. Это может произойти гораздо позже, а может, и вовсе никогда не произойти.

Ответ №2:

То, что ты хочешь, немного странно. Вы хотите волшебным образом остановить функцию тайм-аута, просто присвоив значение null переменной, которая ранее запустила функцию тайм-аута.

Что вы скорее хотите, так это иметь метод, который останавливает функцию тайм-аута. Вызов setTimeout возвращает обработчик. Сохраните этот обработчик и вызовите встроенный метод

clearTimeout(handler)

Комментарии:

1. Я думаю, вы неправильно поняли вопрос. Тайм-аут существует только для того, чтобы проиллюстрировать один момент.

2. Без тайм-аута ни одна функция все равно не будет выполнена.