Будет ли поддержка Javascript ES6 "сделана" api?

Например

p = new Promise(function (resolve, reject) {
    throw 'err';
});

p.done();

В большинстве обеденных polyfill libs, сделанное вызовет ошибку, и текущее выполнение завершится.

Но если мы используем p.then(), ничего не произойдет. Ошибка проглатывается обещанием. Если мы используем p.catch, у нас нет способа выйти из текущего исполнения. Я хочу добиться чего-то вроде:

try {
    // something
} catch (err) {
    if (check(err)) {
        throw err;
    }
}

Ответ 1

Нет.

Не только .done, вероятно, не будет поддерживаться в будущих версиях спецификации - это не требуется. Цитата из нитей Mariusz связана с:

Доменик:

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

Марк Миллер (который впервые разработал концепцию promises):

Обратите внимание, что слабые ссылки, надеюсь, в ES7, предоставят нам один из диагностических инструментов, необходимых для преодоления этого разрыва. Используя слабые ссылки, если полученное отклоненное обещание будет собрано без уведомления о каких-либо обработчиках, мы можем договориться, что это приведет к диагностике. Реализация обещания должна была бы сохранить причину в исполнителе обещаний (post-mortem gc handler), чтобы у него была диагностика, чтобы сообщить после обнаружения, что обещание было отклонено.

Yehuda Kats на обработчике ошибок RSVP:

Подход, который мы применяем в RSVP, заключается в установке необработанного монитора обещаний, который выдает по умолчанию.

Вы можете выбрать конкретное обещание этого поведения, добавив обработчик сбоя noop, если вы знаете, что будете устанавливать асинхронные обработчики ошибок. Вероятно, у нас будет сахар для этого (.undone: p)

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

И, с фактического репо, которое предшествовало спецификации, Доменик сказал:

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


Комитет по спецификациям не просто игнорировал .done, они считали, что это не нужно и склонны к ошибкам. Новые библиотеки современных обещаний автоматически обнаруживают необработанные отказы - два примера этого - это когда promises и Bluebird promises, которые выдвинули идею.

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

Не верьте мне? Откройте Firefox и поиграйте со своим родным promises:

p = new Promise(function (resolve, reject) {
    throw 'err';
});
// Logs as error: Unhandled error: `err`

Проще говоря - firefox использует крючки для сбора мусора, чтобы определить promises, были расположены в необработанном состоянии и запускает глобальный обработчик ошибок, который по умолчанию записывается на экран.

Теперь проблема с native promises еще не очень удобна в использовании - так как в IE они не существуют и в Chrome необработанное обнаружение отбраковки еще не реализовано, но оно приближается, и оно будет там. Тем временем вы можете использовать совместимую с ES6 библиотеку, такую ​​как Bluebird, которая сделает это отслеживание отклонения для вас.

Если вы хотите выполнить polyfill (что я настоятельно рекомендую против), то polyfill от torazaburo имеет несколько недостатков. Он объявляет перечислимое свойство на прототипе обещания, и обычно это не так, как была спроектирована спецификация - вы должны подклассифицировать promises, чтобы расширить их, а не пытаться обезглавить их - к сожалению, никакие реализации в настоящее время не поддерживают это.

Короче говоря:

  • Подождите, пока пользовательский promises стабилизируется, прежде чем вы их используете, - тем временем вы можете использовать библиотеки, которые реализуют спецификацию, такую ​​как Bluebird. Когда он стабилизирует отсутствие .done, это не будет проблемой.
  • Используйте шаблоны для обнаружения ошибок - например, проверьте шаблон удаления здесь.
  • Используйте инструменты разработчика, когда они доступны, длинные трассировки стека и асинхронная отладка - большие плюсы. Также обратите внимание, что вы не должны бросать строки, если хотите значимые трассировки стека.

Удачи и счастливого кодирования.

Ответ 2

Нет, AFAIK done не входит в спецификацию. Чтобы подражать его поведению, вы должны выбросить исключение на следующий тик, вне сферы действия цепочки promises:

p.catch(function(e) { 
    setTimeout(function() { throw e; });
});

Это, по сути, как библиотеки реализуют done. См. Выдержку из Q-документов:

Во многом как then, но... результирующая причина отклонения выбрана как исключение в будущем повороте цикла событий.

Внедрение done самостоятельно

Если вы хотите реализовать приблизительную семантику done, как это обычно понимается, тогда что-то вроде:

Promise.prototype.done = function(onFulfilled, onRejected) {
    this
        .then(onFulfilled, onRejected)
        .catch(function(e) {
            setTimeout(function() { throw e; });
        })
    ;
};

Настройка обработчика ошибок

Если вам нужна возможность самостоятельно обрабатывать эти ошибки, вы можете настроить обработчик ошибок:

Promise.onError = function(e) {
    console.log("The sky is falling", e);
    throw e;
};

Затем вызовите обработчик следующего тика:

Promise.prototype.done = function(onFulfilled, onRejected) {
    this
        .then(onFulfilled, onRejected)
        .catch(function(e) {
            setTimeout(Promise.onError || function() { throw e; }, 1, e);
        })
    ;
};

Ответ 3

Текущая инструкция TC39 заключается в том, что эта проблема может быть и должна решаться изначально в браузерах с инструментами разработчика. Поэтому они не обеспечивают done внутри встроенного API.

Это действительно спорное решение, см следующих ссылок для дискуссий по этому вопросу:

https://github.com/domenic/promises-unwrapping/issues/19

http://mozilla.6506.n7.nabble.com/Where-d-Promise-done-go-td281461.html

https://github.com/promises-aplus/promises-spec/issues/43

https://github.com/slightlyoff/Promises/issues/33