Являются ли JavaScript вечно ожидающие обещания плохими?

Скажи, у меня есть обещание под названием myPromи сказать, что у меня есть обработчики успеха и ошибок под названием onSuccess а также onError,

Всякий раз, когда мое обещание занимает больше 10 секунд, я хочу функцию timeoutHandler быть выполненным, но если это произойдет, ни onSuccess ни onError должен быть выполнен. (Точно так же, если либо onSuccess или же onError работает, я не хочу, чтобы мой timeoutHandler быть выполненным.)

Я придумал следующий фрагмент для этого.

new Promise((suc, err) => {
    let outOfTime = false;
    const timeoutId = window.setTimeout(() => {
        outOfTime = true;
        timeoutHandler();
    }, 10000);
    myProm.then(
        (...args) => {
            if (!outOfTime) {
                window.clearTimeout(timeoutId);
                suc(...args);
            }
        },
        (...args) => {
            if (!outOfTime) {
                window.clearTimeout(timeoutId);
                err(...args);
            }
        }
    );
}).then(onSuccess, onError);

Однако в случае тайм-аута мое новое определенное обещание будет всегда. Может ли это иметь негативные побочные эффекты? Например, среда выполнения не может очистить объект Promise, потому что он все еще ожидает (или что-то в этом роде).

2 ответа

Решение

Там не должно быть никаких побочных эффектов. Это была бы ошибка браузера, если бы не ссылаться Promise в каком бы состоянии ни находились ресурсы.

Просто убедитесь, что вы не держите ссылки на Promise возражать, и все будет в порядке.

Помните, что некоторые API, такие как setTimeout сохранит ссылку на закрытие до значения тайм-аута. Это означает, что если у вас большой тайм-аут, например, 10 с, вы должны очистить его, как только он вам больше не нужен. В противном случае ваш код может вызвать тысячи setTimeout в течение 10 секунд, и каждый из них будет хранить ссылку на закрытие, которое в вашем случае будет ссылаться на Promise,

Ты можешь использовать Promise.race(), задавать timeoutHandler как функция, которая возвращает отклоненный Promise через десять секунд, иначе onSuccess должен быть вызван при исполнении Promise из myProm

function myProm() {
  return new Promise((success, err) => {
    setTimeout(() => {
      success("myProm")
    }, Math.floor(Math.random() * 11000))
  })
}

function timeoutHandler() {
  return new Promise((_, timeout) => {
    setTimeout(() => {
      timeout(new Error("timeoutHandler"));
    }, 10000)
  })
}

function onSuccess(data) {
  console.log("success", data)
}

function onError(err) {
  console.log("err:", err)
}

function onTimeout(e) {
  if (e.message && e.message === "timeoutHandler") {
    console.log(e.message + " handled");
  }
  else { 
    onError(e)
  }
}

Promise.race([myProm(), timeoutHandler()])
.then(onSuccess, onTimeout);

plnkr http://plnkr.co/edit/9UD5syOEOc1oQGdRTRRm?p=preview

Другие вопросы по тегам