Quero trabalhar com promessas, mas tenho uma API de retorno de chamada em um formato como:
1. Carregamento do DOM ou outro evento único:
window.onload; // set to callback
...
window.onload = function() {
};
2. Retorno de chamada simples:
function request(onChangeHandler) {
...
}
request(function() {
// change happened
...
});
3. Retorno de chamada no estilo do nó ("nodeback"):
function getStuff(dat, callback) {
...
}
getStuff("dataParam", function(err, data) {
...
})
4. Uma biblioteca inteira com retornos de chamada no estilo do nó:
API;
API.one(function(err, data) {
API.two(function(err, data2) {
API.three(function(err, data3) {
...
});
});
});
new Promise
acréscimo sobrecarga significativa? Estou querendo agrupar todas as minhas funções síncronas de Noje.js. em uma promessa, para remover todo o código síncrono do meu aplicativo Node, mas essa é uma prática recomendada? Em outras palavras, uma função que aceita um argumento estático (por exemplo, uma seqüência de caracteres) e retorna um resultado calculado, devo enviá-lo em uma promessa? ... Li em algum lugar que você não deve ter nenhum código síncrono no Nodejs.Respostas:
As promessas têm estado, elas começam como pendentes e podem resolver:
As funções de retorno promissor nunca devem ser lançadas ; elas devem retornar rejeições. O lançamento de uma função de retorno de promessa forçará você a usar os modos a
} catch {
e a.catch
. As pessoas que usam APIs prometidas não esperam que as promessas sejam lançadas. Se você não tem certeza de como as APIs assíncronas funcionam em JS - consulte esta resposta primeiro.1. Carregamento do DOM ou outro evento único:
Portanto, criar promessas geralmente significa especificar quando elas se estabelecem - ou seja, quando elas passam para a fase cumprida ou rejeitada para indicar que os dados estão disponíveis (e podem ser acessados com
.then
).Com implementações de promessa modernas que suportam o
Promise
construtor como as promessas nativas do ES6:Você usaria a promessa resultante da seguinte maneira:
Com bibliotecas que suportam adiado (Vamos usar $ q para este exemplo aqui, mas também usaremos o jQuery posteriormente):
Ou com uma jQuery como API, conectando-se a um evento que acontece uma vez:
2. Retorno de chamada simples:
Essas APIs são bastante comuns, pois bem ... retornos de chamada são comuns em JS. Vejamos o caso comum de ter
onSuccess
eonFail
:Com implementações de promessa modernas que suportam o
Promise
construtor como as promessas nativas do ES6:Com bibliotecas que suportam adiado (Vamos usar jQuery para este exemplo aqui, mas também usamos $ q acima):
O jQuery também oferece um
$.Deferred(fn)
formulário, que tem a vantagem de nos permitir escrever uma expressão que emula muito de perto onew Promise(fn)
formulário, da seguinte maneira:Nota: Aqui exploramos o fato de que os métodos
resolve
ereject
métodos adiados por jQuery são "destacáveis"; ie eles estão ligados à instância de um jQuery.Deferred (). Nem todas as bibliotecas oferecem esse recurso.3. Retorno de chamada no estilo do nó ("nodeback"):
Os retornos de chamada no estilo do nó (nodebacks) têm um formato específico em que os retornos de chamada são sempre o último argumento e seu primeiro parâmetro é um erro. Vamos primeiro promisificar um manualmente:
Para:
Com adiados, você pode fazer o seguinte (vamos usar Q neste exemplo, embora Q agora suporte a nova sintaxe que você preferir ):
Em geral, você não deve prometer demais as coisas manualmente, a maioria das bibliotecas promissoras que foram projetadas com o Node em mente, assim como as promessas nativas no Nó 8+, têm um método interno para prometer nodebacks. Por exemplo
4. Uma biblioteca inteira com retornos de chamada no estilo do nó:
Não há regra de ouro aqui, você as promete uma a uma. No entanto, algumas implementações promissoras permitem fazer isso em massa, por exemplo, no Bluebird, converter uma API nodeback em uma API promissora é tão simples quanto:
Ou com promessas nativas no Node :
Notas:
.then
manipulador, não precisa promisificar as coisas. O retorno de uma promessa de um.then
manipulador resolverá ou rejeitará o valor dessa promessa. Jogando de um.then
manipulador também é uma boa prática e rejeitará a promessa - esta é a famosa promessa de lance de segurança.onload
caso real , você deve usar emaddEventListener
vez deonX
.fonte
resolve()
ereject()
são escritos para serem reutilizáveis, atrevo-me que a minha edição sugerida é relevante porque oferece um exemplo jQuery da forma$.Deferred(fn)
, o que está faltando de outra maneira. Se apenas um exemplo do jQuery for incluído, sugiro que seja desse formato e nãovar d = $.Deferred();
etc., pois as pessoas devem ser encorajadas a usar o$.Deferred(fn)
formulário muitas vezes negligenciado , além disso, em uma resposta como essa, coloca o jQuery mais parecido com o bibliotecas que usam o padrão revelador do construtor .$.Deferred(fn)
, se você editar isso em vez do exemplo existente nos próximos 15 minutos, tenho certeza de que posso tentar aprová-lo a tempo :) :)util.promisify
que o Node.js adicionará ao seu núcleo a partir do RC 8.0.0. Seu funcionamento não é muito diferente do BluebirdPromise.promisify
, mas tem a vantagem de não exigir dependências adicionais, caso você queira apenas o Promise nativo. Eu escrevi um post sobre util.promisify para quem quiser ler mais sobre o assunto.Hoje, eu posso usar
Promise
noNode.js
como um método Javascript simples.Um exemplo simples e básico de
Promise
(com o KISS ):Código da API Javascript assíncrona simples :
Promise
Código da API Javascript Assíncrona:(Eu recomendo visitar esta bela fonte )
Também
Promise
pode ser usado junto com oasync\await
inES7
para fazer com que o fluxo do programa aguarde umfullfiled
resultado como o seguinte:Outro uso com o mesmo código usando o
.then()
métodoPromise
Também pode ser usado em qualquer plataforma que é baseado em Node.js comoreact-native
.Bônus : um método híbrido
(presume-se que o método de retorno de chamada tenha dois parâmetros como erro e resultado)
O método acima pode responder ao resultado de retorno de chamada à moda antiga e ao uso do Promise.
Espero que isto ajude.
fonte
Antes de converter uma função como promessa no Node.JS
Depois de convertê-lo
Caso você precise lidar com várias solicitações
fonte
Não acho que a
window.onload
sugestão do @Benjamin funcione o tempo todo, pois não detecta se é chamada após o carregamento. Fui mordido por isso muitas vezes. Aqui está uma versão que sempre deve funcionar:fonte
setTimeout(resolve, 0)
(ousetImmediate
, se disponível) para garantir que seja chamado de forma assíncrona?resolve
síncrona é bom. Osthen
manipuladores da Promise são garantidos pela estrutura para serem chamados de forma assíncrona , independentemente de seremresolve
chamados de forma síncrona.O Node.js. 8.0.0 inclui uma nova
util.promisify()
API que permite que as APIs padrão do estilo de retorno de chamada do Node.j sejam agrupadas em uma função que retorna uma Promessa. Um exemplo de uso deutil.promisify()
é mostrado abaixo.Consulte Suporte aprimorado para promessas
fonte
No candidato a lançamento do Node.js. 8.0.0, há um novo utilitário
util.promisify
(que escrevi sobre util.promisify ), que encapsula a capacidade de prometer qualquer função.Não é muito diferente das abordagens sugeridas nas outras respostas, mas tem a vantagem de ser um método central e não exigir dependências adicionais.
Então você tem um
readFile
método que retorna um nativoPromise
.fonte
util.promisify
duas vezes (em 2014, quando essa pergunta foi escrita, e há alguns meses atrás - que eu insisti como membro principal do Node e é a versão atual que temos no Node). Como ainda não está disponível ao público - ainda não o adicionei a esta resposta. Gostaríamos profundamente Agradecemos o feedback uso embora e conhecer o que algumas armadilhas são, a fim de ter melhores docs para o lançamento :)util.promisify
em seu blog :)util.promisify.custom
símbolo, é possível substituir o resultado do util.promisify? Para ser sincero, foi uma falta intencional, porque ainda não consegui encontrar um caso de uso útil. Talvez você possa me dar algumas informações?fs.exists
ou APIs que não seguem a convenção do Nó - um pássaro azulPromise.promisify
as interpretaria mal, mas as interpretariautil.promisify
corretamente.Você pode usar promessas nativas do JavaScript com o Nó JS.
Link de código do My Cloud 9: https://ide.c9.io/adx2803/native-promises-in-node
fonte
Com o simples javaScript de baunilha antigo, aqui está uma solução para promisificar um retorno de chamada da API.
fonte
A biblioteca Q da kriskowal inclui funções de retorno de chamada para promessa. Um método como este:
pode ser convertido com Q.ninvoke
fonte
Q.denodeify
. Precisamos enfatizar os auxiliares da biblioteca?Quando você tem algumas funções que recebem um retorno de chamada e deseja que elas retornem uma promessa, você pode usar essa função para fazer a conversão.
fonte
Sob o nó v7.6 +, que possui promessas e assíncronas:
Como usar:
fonte
No Node.js 8, você pode prometer métodos de objeto em tempo real usando este módulo npm:
https://www.npmjs.com/package/doasync
Ele usa util.promisify e Proxies para que seus objetos permaneçam inalterados. A memorização também é feita com o uso de WeakMaps). aqui estão alguns exemplos:
Com objetos:
Com funções:
Você pode até usar nativo
call
eapply
vincular algum contexto:fonte
Você pode usar o Promise nativo no ES6, por exemplo, para lidar com setTimeout:
Neste exemplo, a Promessa não tem motivos para falhar, portanto
reject()
nunca é chamada.fonte
A função de estilo de retorno de chamada sempre é assim (quase todas as funções no node.js são desse estilo):
Esse estilo tem o mesmo recurso:
a função de retorno de chamada é passada pelo último argumento.
a função de retorno de chamada sempre aceita o objeto de erro como seu primeiro argumento.
Portanto, você pode escrever uma função para converter uma função com este estilo assim:
Para ser mais conciso, o exemplo acima usou o ramda.js. O Ramda.js é uma excelente biblioteca para programação funcional. No código acima, usamos o método apply (como javascript
function.prototype.apply
) e anexado (como javascriptfunction.prototype.push
). Portanto, podemos converter a função de estilo de retorno de chamada para prometer a função de estilo agora:A função toPromise e checkErr é propriedade da biblioteca berserk , é uma bifurcação da biblioteca de programação funcional por ramda.js (criada por mim).
Espero que esta resposta seja útil para você.
fonte
Você pode fazer algo assim
Então use
fonte
es6-promisify
converte funções baseadas em retorno de chamada em funções baseadas em Promise.Ref: https://www.npmjs.com/package/es6-promisify
fonte
Minha versão promisify de uma
callback
função é aP
função:A
P
função requer que a assinatura de retorno de chamada sejacallback(error,result)
.fonte
util.promisify(fn)
(err, value) => ...
ou você deve definir uma customizada (consulte Funções prometidas personalizadas). Obrigado boa catcha.var P = function (fn, ...args) { return new Promise((resolve, reject) => fn.call(this, ...args, (error, result) => error ? reject(error) : resolve(result))); };
faria a mesma coisa que a sua e é muito mais simples.Abaixo está a implementação de como uma função (API de retorno de chamada) pode ser convertida em uma promessa.
fonte
É um atraso de 5 anos, mas eu queria postar aqui minha versão promesify, que pega funções da API de retorno de chamada e as transforma em promessas
Dê uma olhada nesta versão muito simples aqui: https://gist.github.com/jdtorregrosas/aeee96dd07558a5d18db1ff02f31e21a
fonte