Seja uma Promessa ES6 ou Promessa bluebird, Q Promise, etc.
Como faço para testar se um determinado objeto é uma promessa?
javascript
promise
q
bluebird
es6-promise
o carneiro
fonte
fonte
.then
método, mas isso não lhe diria que o que você tem é uma promessa definitivamente. Tudo o que você saberia naquele momento é que você tem algo que expõe um.then
método, como uma Promessa..then
método que não seja uma promessa, não se comporte como uma promessa e não tenha intenção de ser usado como uma promessa. A verificação de um.then
método apenas informa que o objeto if não possui um.then
método, então você não tem uma Promessa. O inverso - que a existência de um.then
meio de métodos que você faz tem uma promessa - não é necessariamente verdade..then
método. Sim, isso tem potencial para falsos positivos, mas é a suposição de que todas as bibliotecas promissoras dependem (porque é nisso que elas podem confiar). A única alternativa, até onde posso ver, é aceitar a sugestão de Benjamin Gruenbaum e executá-la no conjunto de testes promissores. Mas isso não é prático para o código de produção real.Respostas:
Como uma biblioteca de promessas decide
Se tiver uma
.then
função - esse é o única padrão das bibliotecas de promessas.A especificação Promises / A + possui uma noção chamada
then
capaz, que é basicamente "um objeto com umthen
método". Promessas vão e devem assimilar qualquer coisa com um método then. Toda a implementação da promessa que você mencionou faz isso.Se olharmos para a especificação :
Também explica a justificativa para esta decisão de design:
Como você deve decidir
Você não deve - em vez disso, ligar
Promise.resolve(x)
(Q(x)
em Q) que sempre converterá qualquer valor outhen
capacidade externa em uma promessa confiável. É mais seguro e fácil do que executar essas verificações você mesmo.realmente precisa ter certeza?
Você sempre pode executá-lo no conjunto de testes : D
fonte
Para verificar se algo é promissor, complica desnecessariamente o código, basta usar
Promise.resolve
fonte
Aqui está a minha resposta original, que foi ratificada na especificação como a maneira de testar uma promessa:
Isso funciona porque o algoritmo exige explicitamente que
Promise.resolve
deve retornar o objeto exato passado se e somente se for uma promessa pela definição da especificação.Tenho outra resposta aqui, que costumava dizer isso, mas mudei para outra coisa quando não funcionava com o Safari naquele momento. Isso foi há um ano e agora isso funciona de maneira confiável, mesmo no Safari.
Eu teria editado minha resposta original, exceto a que parecia errada, já que agora mais pessoas votaram na solução alterada nessa resposta do que a original. Acredito que esta seja a melhor resposta e espero que você concorde.
fonte
===
vez de==
?Atualização: essa não é mais a melhor resposta. Por favor vote em minha outra resposta .
deve fazê-lo. Observe que isso só pode funcionar de maneira confiável com as promessas nativas do es6.
Se você estiver usando um calço, uma biblioteca de promessas ou qualquer outra coisa que pretenda ser semelhante a uma promessa, pode ser mais apropriado testar um "selecionável" (qualquer coisa com um
.then
método), conforme mostrado em outras respostas aqui.fonte
Promise.resolve(obj) == obj
não funcionará no Safari. Use eminstanceof Promise
vez disso.obj && typeof obj.then == 'function'
, porque ele funcionará com todos os tipos de promessas e é realmente o caminho recomendado pelas especificações e usado pelas implementações / polyfills. O nativo,Promise.all
por exemplo, funcionará em todas asthen
habilidades, não apenas em outras promessas nativas. O mesmo deve acontecer com o seu código. Portanto,instanceof Promise
não é uma boa solução.console.log(typeof p, p, p instanceof Promise);
produz esta saída:object Promise { <pending> } false
. Como você pode ver, é uma promessa certa - e ainda assim oinstanceof Promise
teste retornafalse
?fonte
Para ver se o objeto fornecido é uma promessa do ES6 , podemos fazer uso deste predicado:
Call
ingtoString
diretamente doObject.prototype
retorna uma representação de string nativa do tipo de objeto especificado, que está"[object Promise]"
em nosso caso. Isso garante que o objeto fornecidotoString
Método auto-escrito do objeto fornecido.instanceof
ouisPrototypeOf
.No entanto, qualquer objeto host específico , que tenha sua tag modificada por
Symbol.toStringTag
, pode retornar"[object Promise]"
. Este pode ser o resultado pretendido ou não, dependendo do projeto (por exemplo, se houver uma implementação personalizada do Promise).Para ver se o objeto é de uma promessa nativa do ES6 , podemos usar:
De acordo com esta e esta seção da especificação, a representação de string da função deve ser:
que é tratado em conformidade acima. O FunctionBody está
[native code]
em todos os principais navegadores.MDN:
Function.prototype.toString
Isso funciona em vários contextos de ambiente também.
fonte
Não é uma resposta para a pergunta completa, mas acho que vale a pena mencionar que no Node.js. 10
isPromise
foi adicionada uma nova função util chamada que verifica se um objeto é uma promessa nativa ou não:fonte
É assim que o pacote graphql-js detecta promessas:
value
é o valor retornado da sua função. Estou usando esse código no meu projeto e não tenho nenhum problema até agora.fonte
Aqui está o formulário de código https://github.com/ssnau/xkit/blob/master/util/is-promise.js
se um objeto com um
then
método, ele deve ser tratado como umPromise
.fonte
Caso você esteja usando o Typecript , gostaria de acrescentar que você pode usar o recurso "predicado de tipo". Basta envolver a verificação lógica em uma função que retorne
x is Promise<any>
e você não precisará fazer previsões de digitação. Abaixo, no meu exemplo,c
há uma promessa ou um dos meus tipos que desejo converter em promessa chamando oc.fetch()
métodoMais informações: https://www.typescriptlang.org/docs/handbook/advanced-types.html
fonte
Se você estiver em um método assíncrono, poderá fazer isso e evitar qualquer ambiguidade.
Se a função retornar promessa, aguardará e retornará com o valor resolvido. Se a função retornar um valor, ela será tratada como resolvida.
Se a função não retornar uma promessa hoje, mas amanhã retornar uma ou for declarada assíncrona, você estará à prova de futuro.
fonte
Promise.resolve()
fonte
Eu uso essa função como uma solução universal:
fonte
depois de procurar uma maneira confiável de detectar funções assíncronas ou até promessas , acabei usando o seguinte teste:
fonte
Promise
e criar instâncias disso, esse teste poderá falhar. isso deve funcionar para a maioria do que você está tentando testar.fn.constructor.name === 'AsyncFunction'
está errado - isso significa alguma coisa é uma função assíncrona e não uma promessa - também não é garantido para o trabalho porque as pessoas podem subclasse promessasES6:
fonte
toString
método pode simplesmente retornar uma string que inclui"Promise"
.'NotAPromise'.toString().includes('Promise') === true