У меня есть чистое обещание JavaScript (встроенная реализация или poly-fill):
var promise = new Promise(function (resolve, reject) { /* ... */ });
Согласно спецификации , Promise может быть одним из:
- «решен» и «решен»
- «урегулирован» и «отклонен»
- «В ожидании»
У меня есть случай, когда я хочу синхронно опросить Обещание и определить:
Посыл обещан?
если да, то разрешено ли обещание?
Я знаю, что могу использовать #then()
для планирования асинхронной работы после изменения состояния Promise. Я НЕ спрашиваю, как это сделать.
Этот вопрос конкретно о синхронном опросе состояния Обещания . Как мне этого добиться?
javascript
promise
es6-promise
jokeyrhyme
источник
источник
var promiseStatus = NEW_PRIVATE("Promise#status");
,PromiseSet
функция уSET_PRIVATE(promise, promiseStatus, status);
console.log(Promise.new((resolve, reject) => {})
=>Promise { <pending> }
Ответы:
Для родных обещаний JavaScript такого API не существует. Это невозможно сделать с помощью родных обещаний. В спецификации не указан такой метод.
Пользовательские библиотеки могут сделать это, и если вы нацелены на конкретный движок (например, v8) и имеете доступ к коду платформы (то есть вы можете писать код в ядре ), то вы можете использовать специальные инструменты (например, частные символы) для достижения этой цели. , Это супер специфично, хотя и не в пользовательской среде.
источник
.any
вместо этого разобраться и сделать ошибку, потому что Марк настоял. ВоPromise.race([])
-первых , это обещание, ожидающее навсегда (а не ошибка), вы обычно хотите первое успешное обещание, а не только первое обещание. Во всяком случае, это не очень относится к заданному вопросу - ОП спрашивал о синхронном осмотре, а не о.race
его многочисленных недостатках.MakeQueryablePromise(Promise.resolve(3)).isResolved
, ложно, но обещание вполне очевидно решено. Не говоря уже о том, что в ответе также неправильно используются термины «решен» и «выполнен». Чтобы сделать этот ответ, вы можете просто добавить.then
обработчик самостоятельно, что полностью пропускает точку синхронной проверки.Обещание-статус-асинхронный делает свое дело. Это асинхронный режим, но он не использует
then
ожидание разрешения обещания.источник
Нет, нет API синхронизации, но вот моя версия асинхронности
promiseState
(с помощью @Matthijs):источник
Promise.race([ Promise.resolve(p).then(() => "fulfilled", () => "rejected"), Promise.resolve().then(() => "pending") ]);
хотя это кажется мне более безопасным:const t = {}; return Promise.race([p,t]).then(v => v === t ? "pending" : "fulfilled", () => "rejected")
и избегает создания дополнительных обещаний, которые сохраняются до тех пор, пока оригинал p находится в ожидании.Вы можете сделать гонку с Promise.resolve.
Это не синхронно, но происходит сейчас.
Небольшой скрипт для тестирования и понимания их значения асинхронно
результаты с задержкой (0) (прокомментируйте время задержки)
и результаты этого теста с Firefox (Chrome держать порядок)
Обещание государства сделать .race и .then: уровень 2
источник
'a value that p should not return'
, чтобы использовать SymbolSymbol
будет уникальным значением, поэтому вам никогда не придется угадывать, какое «значение [...] p не должно возвращаться». Тем не менее, ссылка на конкретный объект будет работать так же хорошо.Вы можете использовать (безобразный) хак в Node.js, пока не будет предложен собственный метод:
источник
Promise.prototype.isPending = function(){ return util.inspect(this).indexOf("<pending>")>-1; }
process.binding('util').getPromiseDetails
Promise.resolve('<pending>')
.в узле, скажем, недокументированный внутренний
process.binding('util').getPromiseDetails(promise)
источник
Обновлено: 2019
Bluebird.js предлагает это: http://bluebirdjs.com/docs/api/isfulfilled.html
Если вы предпочитаете создать свою собственную оболочку, вот хороший блог об этом.
Поскольку JavaScript является однопоточным, трудно найти достаточно распространенный вариант использования, чтобы оправдать включение этого в спецификацию. Лучшее место, чтобы узнать, выполнено ли обещание, находится в .then (). Проверка выполнения Обещания создаст цикл опроса, который, скорее всего, будет неправильным направлением.
async / await - хорошая конструкция, если вы хотите синхронно рассуждать асинхронный код.
Еще один полезный вызов - Promise.all ()
Когда я впервые добрался до этого ответа, это был тот вариант использования, который я искал.
источник
Вы можете обернуть свои обещания таким образом
источник
.then
всегда выполняется асинхронно, OP, который хочет проверить обещание в один и тот же ход , не получит правильный результат здесь. Примечание ОП спрашивал конкретно о синхронной проверке и упоминал, что они уже знают об асинхронной проверке.Это действительно довольно раздражает, что эта базовая функциональность отсутствует. Если вы используете node.js, то я знаю два обходных пути, ни один из них не очень красивый. Оба фрагмента ниже реализуют один и тот же API:
Кажется, нет никакого способа различить последние два состояния обещания, используя любой трюк.
1. Используйте API отладки V8
Это тот же трюк, который
util.inspect
использует.2. Синхронно запускать микрозадачи
Это позволяет избежать API отладки, но имеет некоторую пугающую семантику, так как все ожидающие выполнения микрозадачи и
process.nextTick
обратные вызовы запускаются синхронно. У этого также есть побочный эффект предотвращения ошибки «отклонения необработанного обещания», когда-либо вызванной для проверенного обещания.источник
process._tickCallback
(или даже обычный% RunMicrotick) - это будет случайным образом нарушать ваш код. Я отчаянно пытался заставить его работать (в основном для ложных таймеров в асинхронных функциях), и он никогда не был достаточно стабильным со стороны узла. Я как бы бросил работать над этим. API зеркала отладки V8 здесь вполне уместно.DeprecationWarning: DebugContext has been deprecated and will be removed in a future version.
:( Похоже, V8 удалил егоprocess.binding('util').getPromiseDetails( promise )
возвращается[ 0, ]
для ожидающих,[ 1, value ]
для выполненных и[ 2, value ]
отклоненных.Предупреждение: этот метод использует недокументированные внутренние компоненты Node.js и может быть изменен без предупреждения.
В Node вы можете синхронно определять состояние обещания, используя
process.binding('util').getPromiseDetails(/* promise */);
.Это вернет:
[0, ]
для ожидания,[1, /* value */]
за выполненное, или[2, /* value */]
за отклонено.Оборачиваем это в вспомогательную функцию:
источник
jest
(это единственное место, которое меня интересует, правда). Функция существует, но всегда, кажется, возвращаетсяundefined
. Как мне узнать, что не так?mocha
; никогда не пробовал с этимjest
все же. Может быть, начать новый вопрос со ссылкой здесь и включить вашу версию Node.js, а такжеjest
версию?Promise
который я использовал только для проверки того, что должно происходить, покаPromise
находится в ожидании, но я решил, что пока то, что я написал, работает, то нет необходимости проверять это в дополнение к тому, что на это опирается.что вы можете сделать, это использовать переменную для хранения состояния, вручную установить состояние для этой переменной и проверить эту переменную.
конечно, это означает, что вы должны иметь доступ к исходному коду обещания. Если вы этого не сделаете, то вы можете сделать:
Мое решение - больше кодирования, но я думаю, что вам, вероятно, не придется делать это для каждого обещания, которое вы используете.
источник
Начиная с версии 8 Node.js, теперь вы можете использовать пакет мудрого контроля для синхронной проверки собственных обещаний (без каких-либо опасных хаков).
источник
Вы можете добавить метод в Promise.prototype. Это выглядит так:
Отредактировано: первое решение не работает должным образом, как большинство ответов здесь. Он возвращает «в ожидании» до тех пор, пока не будет вызвана асинхронная функция «.then», что не происходит немедленно. (То же самое касается решений, использующих Promise.race). Мое второе решение решает эту проблему.
Вы можете использовать его на любом обещании. Например:
Второе (и правильное) решение:
И используйте это:
Примечание : в этом решении вам не нужно использовать оператор «new».
источник
Вот более конкретная версия QueryablePromise для es6, которая позволяет затем выполнять цепочку и перехватывать после первого разрешения, а также немедленно разрешать или отклонять, чтобы поддерживать API в соответствии с собственным Promise.
источник
await
использование к ответу @ jib с идиоматическим прототипированием.обратите внимание, что эта асинхронная функция выполняет «почти» сразу же, как синхронизируемая функция (или фактически может быть мгновенной).
источник
2019:
Простой способ сделать это, как я знаю
thenable
, это супер тонкая обертка вокруг обещания или любая асинхронная работа.источник
Вы можете создать свой собственный подкласс, скажем
QueryablePromise
, наследуя от нативно доступногоPromise
класса, экземпляры которого будут иметьstatus
доступное свойство, которое вы можете использовать для синхронного запроса статуса объектов обещания . Реализация этого может быть замечена ниже или обратитесь к этому для лучшего объяснения.источник
fetch
он вернет родное обещание. Как ваш класс поможет с этим?const queryableFetch = new QueryablePromise((resolve, reject) => {fetch(/.../).then((data) => resolve(data)) })
? Или есть проблема с этим? : /, err => reject(err)
в качестве второго аргумента,then
иначе оно не будет правильно распространять ошибки (среди причин, по которым это считается анти-паттерном конструктора обещаний ). Хотя это не совсем синхронно (например, не обнаружит уже выполненное обещание), но, возможно, полезно в тех случаях, когда вы не контролируете звонящего и ответ требуется немедленно.Там еще один элегантный и Hacky способ проверки , если обещание еще находится на рассмотрении только путем преобразования всего объекта в строку и проверить его с помощью инспектировать , как это:
util.inspect(myPromise).includes("pending")
.Протестировано на Node.js 8,9,10,11,12,13
Вот полный пример
Результат:
источник
Если вы используете ES7 экспериментальный, вы можете использовать async, чтобы легко обернуть обещание, которое вы хотите слушать.
источник
Я написал небольшой пакет npm, promise-value, который предоставляет упаковщик обещаний с
resolved
флагом:https://www.npmjs.com/package/promise-value
Это также дает синхронный доступ к значению обещания (или ошибке). Это не изменяет сам объект Promise, следуя за переносом, а не за расширением шаблона.
источник
Это старый вопрос, но я пытался сделать что-то подобное. Мне нужно, чтобы работники продолжали работать. Они структурированы в обещании. Мне нужно отсканировать и посмотреть, были ли они решены, отклонены или все еще ожидают. Если решено, мне нужно значение, если отклонено, сделать что-то, чтобы исправить проблему или в ожидании. Если решено или отклонено, мне нужно запустить другое задание, чтобы продолжать работу. Я не могу найти способ сделать это с Promise.all или Promise.race, так как я продолжаю работать с обещаниями в массиве и не могу найти способ их удалить. Поэтому я создаю работника, который делает трюк
Мне нужна функция генератора обещаний, которая возвращает обещание, которое разрешается или отклоняется по мере необходимости. Он вызывается функцией, которая устанавливает структуру, чтобы знать, что делает обещание.
В приведенном ниже коде генератор просто возвращает обещание, основанное на setTimeout.
Вот
doWork возвращает объект, содержащий обещание, его состояние и возвращаемое значение.
Следующий код запускает цикл, который проверяет состояние и создает новых рабочих, чтобы держать его на 3 работающих работниках.
Протестировано в node.js
Кстати, не в этом ответе так много, но в других на подобные темы, я НЕНАВИЖУ это, когда кто-то говорит «ты не понимаешь» или «это не так работает», я обычно предполагаю, что спрашивающий знает, чего они хотят. Предлагать лучший способ - это здорово. Терпеливое объяснение того, как работают обещания, также было бы хорошо.
источник
Я обнаружил, что это решение простое и позволяет мне продолжать использовать собственные обещания, но добавляет полезные синхронные проверки. Мне также не нужно было тянуть всю библиотеку обещаний.
CAVEAT: это работает только в том случае, если в текущем потоке выполнения есть какой-то разрыв, чтобы выполнить обещания ДО проверки синхронных конструкций. Это делает его более ограниченным по полезности, чем я изначально думал - хотя он по-прежнему полезен для моего варианта использования (спасибо Бенджамину Грюнбауму за указание на это)
Из https://ourcodeworld.com/articles/read/317/how-to-check-if-a-javascript-promise-has-been-fulfilled-rejected-or-resolved, который основывает свой ответ на « Есть ли способ скажите, выполнено ли обещание ES6 / отклонено / разрешено?
источник
MakeQueryablePromise(Promise.resolve(3)).isResolved
, ложно, но обещание вполне очевидно разрешено. Не говоря уже о том, что в ответе также неправильно используются термины «решен» и «выполнен». Чтобы сделать этот ответ, вы можете просто добавить.then
обработчик самостоятельно, что полностью пропускает точку синхронной проверки.let wrappedPromise = MakeQueryablePromise(Promise.resolve(3)); setTimeout(function() {console.log(wrappedPromise.isFulfilled())}, 1);
Который, пока вы делаете это, это работает хорошо. Но вы должны понимать этот факт, чтобы это было полезно. Я обновлю описание с этой оговоркой. Я также согласен с тем, что именование функций может быть лучше / более идиоматичным.then
выполнить первоначальное обещание и выполнить то же самое, поскольку оно в любом случае асинхронно. Есть способ сprocess.binding('util').getPromiseDetails
этим, кажется, работает, но он использует частный API