Почему я не могу заменить библиотеку trycatch на Promise.method от bluebird?

Поэтому я подумал, что могу использовать Promise.method() из bluebird для замены библиотеки trycatch, которую я использовал.

К сожалению, кажется, что он не улавливает выброшенную ошибку из setTimeout.

у меня что-то в этом духе

function run()
{
    var p = Promise.pending()

    var inner = Promise.method(function()
    {
        //some code that could potentially get stuck

        setTimeout(function $timeoutTaskKill() {
            if (p.promise.isPending())
            {
                var duration = moment.duration(taskTimeout).seconds();
                throw new Error(util.format('timeout has been reached: %ss', duration));
            }
        }, taskTimeout)
    });

    //pseudo
    inner().then(p.reject, p.resolve);

    return p.promise;
}

Это крашит мой процесс. Когда я использовал библиотеку trycatch вместо Promise.method, она поймала ошибку.


person Madd0g    schedule 03.11.2014    source источник
comment
Это псевдо действительно только псевдо или вы на самом деле используете отложенный антишаблон?   -  person Bergi    schedule 04.11.2014
comment
Я использую анти-шаблон. Я остро осознаю везде, где я не использую return с обещаниями. Это одно из немногих мест. Имеет ли это значение в отношении обработки ошибок?   -  person Madd0g    schedule 04.11.2014
comment
Обратите внимание, что вы используете антишаблон .then(success,fail), а также отложенный антишаблон.   -  person Benjamin Gruenbaum    schedule 04.11.2014
comment
@BenjaminGruenbaum - вот почему я поместил туда псевдо, просто чтобы показать, что на самом деле происходит, когда внутреннее заканчивается, внешнее обещание выполняется / отклоняется.   -  person Madd0g    schedule 04.11.2014


Ответы (1)


trycatch использует домены для обнаружения таких ошибок, а обещания - нет.

Чтобы получить отклоненное обещание, вам нужно сделать это явно. Это можно сделать с помощью throwing из обработчика обещания (then), но не из произвольного асинхронного обратного вызова.

Что ты можешь сделать:

  • На самом деле отклоните обещание обратного вызова:

    setTimeout(function $timeoutTaskKill() {
        var duration = moment.duration(taskTimeout).seconds();
        p.reject(new Error(util.format('timeout has been reached: %ss', duration)));
    }, taskTimeout)
    
  • Используйте обещания. Всегда обещайте на самом низком уровне, в данном случае setTimeout. На самом деле Bluebird уже сделал это за вас: Promise.delay.

    Promise.race([
        actualToDo(),
        Promise.delay(taskTimeout).then(function() {
            var duration = moment.duration(taskTimeout).seconds();
            throw new Error(util.format('timeout has been reached: %ss', duration));
        })
    ])
    
  • Или используйте встроенный в Bluebird timeout() метод.

person Bergi    schedule 03.11.2014
comment
хм. Могу ли я сделать Promise.fulfilled().then() и сделать это из раздела then?? Нет ли более простого способа? РЕДАКТИРОВАТЬ: упс. только что увидел твою правку - person Madd0g; 04.11.2014
comment
@ Madd0g Вы можете просто выполнить inner().timeout(taskTimeout) и получить тот же результат, что и у вас, со всем этим кодом, только с лучшими типами и производительностью. Вот что означает берги с timeout(). - person Benjamin Gruenbaum; 04.11.2014
comment
Берги - возможно, стоит упомянуть, что промисы безопасны для бросков и что для того, чтобы получить эту безопасность бросков, вы должны работать с обещанием API. - person Benjamin Gruenbaum; 04.11.2014
comment
Я думал, что это то, что сделал Promise.method, сделал безопасным бросок функции - person Madd0g; 04.11.2014
comment
@BenjaminGruenbaum Я сказал, что обработчики then безопасны для бросков (и, конечно же, все, что от них происходит). - person Bergi; 04.11.2014
comment
Я хочу решить проблему броска, а не проблему тайм-аута, я использую бросок в других местах и ​​хотел просто попытаться реорганизовать библиотеку trycatch. - person Madd0g; 04.11.2014
comment
@Madd0g: Нет, Promise.method только сделать текущую функцию защищенной от бросков. Если вы выбрасываете из несвязанной (асинхронной) функции, которая вызывается не из Promise.method (но из асинхронной задачи), это невозможно поймать. Если у вас есть несколько случаев этого, используйте мой второй подход - обещание на более низком уровне. - person Bergi; 04.11.2014
comment
Я считаю совершенно неразумным, что я продолжаю получать ответы о том, что этот тип ошибки не может быть обнаружен всякий раз, когда я выхожу из зоны комфорта своих обещаний (и я все время использую throw, я живу в своем уединенном маленьком мире, защищенном обещаниями). Как домены могут быть единственным ответом? Во всяком случае, я решил проблему тайм-аута с помощью метода Promise.delay(). не удалось заставить timeout() ошибиться. - person Madd0g; 04.11.2014
comment
забавно, в прошлый раз я обратился за помощью по подобной проблеме Я получил невозможный ответ от @BenjaminGruenbaum. - person Madd0g; 04.11.2014
comment
Похоже, что эксперты согласны с этим :-) (Вполне разумно) точка зрения заключается в том, что throw действительно возвращает управление синхронно своему < i>вызывающий — который в асинхронном обратном вызове является не кодом, инициировавшим асинхронную задачу, а циклом обработки событий. Единственное решение для их обнаружения — поместить обработчик между циклом событий и обратным вызовом и связать его с обратным вызовом ошибки, предоставленным кодом запуска задачи — это именно то, что делают домены. - person Bergi; 04.11.2014
comment
Что делает код в then() безопасным? Почему я не мог добиться этого, пообещав (в связанном вопросе)? Является ли текущая проблема только частью setTimeout, потому что у таймера нет вызывающего абонента? Страшно иногда осознавать, как много ты не знаешь - person Madd0g; 04.11.2014
comment
Код в then-обратных вызовах безопасен для бросков, потому что библиотека обещаний перехватывает исключения для вас, что возможно, потому что она знает, что делать с перехваченной ошибкой: отклонить возвращенное обещание. Обещание основано на передаче ошибок обратному вызову его узла, он не может обнаруживать произвольные исключения, потому что он не является инициатором асинхронного обратного вызова. Да, это проблема с setTimeout - таймер (цикл событий), который вызывает обратный вызов, не знает, что делать с исключениями, которые к нему всплыли, единственное, что он может сделать, это вызвать глобальное исключение. - person Bergi; 04.11.2014