Как сделать исключение в методе catch Promise в JavaScript? [Дубликат]

Вместо обратных вызовов, которые не существуют в CSS, мы можем использовать свойство transition-delay.

#selector {
    overflow: hidden; // hide the element content, while height = 0
    height: 0; opacity: 0;
    transition: height 0ms 400ms, opacity 400ms 0ms;
}
#selector.visible {
    height: 100%; opacity: 1;
    transition: height 0ms 0ms, opacity 600ms 0ms;
}

Итак, что здесь происходит?

  1. Когда добавлен класс visible, обе height и opacity запускают анимацию без задержки (0 мс), хотя height принимает 0 мс для завершения анимации (эквивалент display: block), а opacity занимает 600 мс.
  2. Когда класс visible удален, opacity запускает анимацию (0 мс задержка, 400 мс), а высота ждет 400 мс и только затем мгновенно восстанавливает начальное значение (эквивалент display: none в обратном вызове анимации) .

Обратите внимание, что этот подход лучше, чем при использовании visibility. В этом случае элемент все еще занимает пространство на странице, и это не всегда удобно.

Для получения дополнительных примеров обратитесь к этой статье .

97
задан Theveloper 8 October 2015 в 16:01
поделиться

6 ответов

Да обещает ошибки проглатывания, и вы можете поймать их только с помощью .catch, как объяснено более подробно в других ответах. Если вы находитесь в Node.js и хотите воспроизвести нормальное поведение throw, выполните трассировку стека стека на консоль и процесс завершения, вы можете сделать

...
  throw new Error('My error message');
})
.catch(function (err) {
  console.error(err.stack);
  process.exit(0);
});
0
ответ дан Jesús Carrera 28 August 2018 в 03:02
поделиться

Согласно spec (см. 3.III.d) :

d. Если вызов затем выдает исключение e, & nbsp; & nbsp; a. Если вы вызываете resolvePromise или rejectPromise, игнорируйте его. & NBSP; & NBSP; б. В противном случае, отклоните обещание с e в качестве причины.

Это означает, что если вы выбрали исключение в функции then, оно будет поймано, и ваше обещание будет отклонено. catch не имеет смысла здесь, это просто ярлык для .then(null, function() {})

Я предполагаю, что вы хотите регистрировать необработанные отклонения в коде. Большинство библиотек обещаний запускает для него unhandledRejection. Вот соответствующий gist с обсуждением об этом.

2
ответ дан just-boris 28 August 2018 в 03:02
поделиться

Я знаю, что это немного поздно, но я столкнулся с этой нитью, и ни одно из решений не было легко реализовать для меня, поэтому я придумал свой собственный:

Я добавил немного помощника функция, которая возвращает обещание, например:

function throw_promise_error (error) {
 return new Promise(function (resolve, reject){
  reject(error)
 })
}

Тогда, если у меня есть определенное место в любой из моих цепочек обещаний, где я хочу выбросить ошибку (и отвергнуть обещание), я просто возвращаю из приведенной выше функции с моей сконструированной ошибкой, например:

}).then(function (input) {
 if (input === null) {
  let err = {code: 400, reason: 'input provided is null'}
  return throw_promise_error(err)
 } else {
  return noterrorpromise...
 }
}).then(...).catch(function (error) {
 res.status(error.code).send(error.reason);
})

Таким образом, я контролирую выброс лишних ошибок из цепочки обещаний. Если вы хотите также обрабатывать «нормальные» обещания, вы можете расширить свой улов, чтобы обрабатывать «самозаброшенные» ошибки отдельно.

Надеюсь, что это поможет, это мой первый ответ на stackoverflow!

0
ответ дан nuudles 28 August 2018 в 03:02
поделиться

Я попробовал метод setTimeout(), подробно описанный выше ...

.catch(function(err) { setTimeout(function() { throw err; }); });

Раздражающе, я обнаружил, что это абсолютно неуместно. Поскольку он выдает асинхронную ошибку, вы не можете обернуть ее внутри оператора try/catch, потому что catch перестанет прослушиваться по ошибке времени.

Я вернул только использование прослушивателя который отлично работал и, поскольку он предназначен для использования JavaScript, был высоко проверяемым.

return new Promise((resolve, reject) => {
    reject("err");
}).catch(err => {
    this.emit("uncaughtException", err);

    /* Throw so the promise is still rejected for testing */
    throw err;
});
3
ответ дан RiggerTheGeek 28 August 2018 в 03:02
поделиться

Важные вещи, чтобы понять здесь

  1. Обе функции then и catch возвращают новые объекты обещания.
  2. Выбрасывая или явно отклоняя, будет перемещать текущий обещают отклоненное состояние.
  3. Поскольку then и catch возвращают новые объекты обещания, они могут быть привязаны.
  4. Если вы бросаете или отклоняете внутри обработчика обещаний (then или catch), он будет обрабатываться в следующем обработчике отклонения по пути цепочки.
  5. Как упоминалось jfriend00, обработчики then и catch не выполняются синхронно. Когда обработчик бросает, он немедленно прекратится. Таким образом, стек будет размотан, и исключение будет потеряно. Вот почему бросание исключения отвергает текущее обещание.

В вашем случае вы отклоняете внутри do1, бросая объект Error. Теперь текущее обещание будет в состоянии отклонения, и управление будет передано следующему обработчику, который в нашем случае then.

Поскольку обработчик then не имеет обработчика отклонения , do2 не будет выполняться вообще. Вы можете подтвердить это, используя console.log внутри него. Поскольку текущее обещание не имеет обработчика отклонения, оно также будет отклонено с использованием значения отклонения от предыдущего обещания, и управление будет передано следующему обработчику, который является catch.

Поскольку catch является обработчиком отклонения, когда вы console.log(err.stack); внутри него, вы можете видеть трассировку стека ошибок. Теперь вы выбрасываете из него объект Error, так что обещание, возвращенное catch, также будет находиться в состоянии отклонения.

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


Вы можете разделить цепочку и понять это лучше, например

var promise = do1().then(do2);

var promise1 = promise.catch(function (err) {
    console.log("Promise", promise);
    throw err;
});

promise1.catch(function (err) {
    console.log("Promise1", promise1);
});

. Вы получите то, что вы получите

Promise Promise { <rejected> [Error: do1] }
Promise1 Promise { <rejected> [Error: do1] }

Внутри обработчика catch вы получаете значение promise объекта как отклоненного.

То же самое, обещание, возвращаемое обработчиком catch 1, также отклоняется с той же ошибкой, с которой promise был отклонен, и мы наблюдаем его во втором обработчике catch.

38
ответ дан thefourtheye 28 August 2018 в 03:02
поделиться

Как объяснили другие, «черная дыра» заключается в том, что метание внутри .catch продолжает цепочку с отклоненным обещанием, и у вас больше нет уловов, что приводит к неразрывной цепочке, которая проглатывает ошибки (плохие!)

Добавьте еще один улов, чтобы увидеть, что происходит:

do1().then(do2).catch(function(err) {
    //console.log(err.stack); // This is the only way to see the stack
    throw err; // Where does this go?
}).catch(function(err) {
    console.log(err.stack); // It goes here!
});

Улов в середине цепочки полезен, когда вы хотите, чтобы цепочка продолжалась, несмотря на неудачный шаг, но повторный бросок полезен для continue failing после выполнения таких действий, как ведение журнала информации или шагов очистки, возможно, даже изменение этой ошибки.

Trick

Чтобы ошибка возникла как ошибка в веб-консоли, как вы изначально планировали, я использую этот трюк:

.catch(function(err) { setTimeout(function() { throw err; }); });

Even номера строк выживают, поэтому ссылка в веб-консоли выводит меня прямо в файл и строку, где произошла ошибка (оригинальная).

Почему это работает

Любое исключение в функции, называемой поскольку обработчик выполнения обещаний или отклонения автоматически преобразуется в отказ от обещания, которое вы должны вернуть. Код обещания, который вызывает вашу функцию, позаботится об этом.

Функция, вызываемая setTimeout, с другой стороны, всегда работает из стабильного состояния JavaScript, то есть работает в новом цикле в цикле событий JavaScript. Исключения там не пойманы ничем и не попадают в веб-консоль. Поскольку err содержит всю информацию об ошибке, включая исходный стек, номер файла и строки, он по-прежнему сообщается правильно.

127
ответ дан Vicky Chijwani 28 August 2018 в 03:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: