Prefácio
A primeira vez que entrei em contato com a promessa foi quando a Microsoft lançou o sistema operacional do Windows 8 em 2012 e estudei usando o HTML5 para escrever aplicativos de metrô com uma atitude curiosa. Naquela época, as interfaces assíncronas na biblioteca Winjs fornecidas com HTML5 estavam todas em forma de promessa, que era simplesmente um livro do céu para mim que acabara de se formar na JavaScript na época. O que eu estava pensando na época era que a Microsoft estava mexendo novamente.
Inesperadamente, em 2015, a promessa foi realmente escrita no padrão ES6. Além disso, uma pesquisa mostra que os programadores JS usam essa coisa bastante alta.
Ironicamente, como a Microsoft, que usou amplamente a promessa na interface de desenvolvimento de aplicativos do metrô já em 2012, seu próprio navegador, ou seja, ainda não apoiava a promessa até morrer em 2015. Parece que a Microsoft não possui essa tecnologia, mas realmente desistiu de tratamento para o IE. . .
Olhando para trás agora, a coisa mais problemática de ver a promessa naquela época foi que os iniciantes parecem incríveis e também são o recurso mais elogiado pelos programadores JS: então a cadeia de chamadas da função.
Em seguida, a cadeia de chamadas da função, essencialmente, é chamar vários processos assíncronos em sequência. Este artigo começa a partir deste ponto e estuda e aprende a característica da promessa.
Promessa resolvida
Considere o cenário a seguir, após a função atrasar por 2 segundos, imprima uma linha de toras e atrasa por 3 segundos e depois atrasa por 4 segundos, imprima uma linha de logs. Isso é uma coisa muito simples em outras linguagens de programação, mas é mais difícil entrar no JS, e o código provavelmente será escrito da seguinte maneira:
var myfunc = function () {setTimeout (function () {console.log ("log1"); setTimeout (function () {console.log ("log2"); setTimeout (function () {console.log ("log3");}, 4000);}, 3000);}, 2000);Devido à estrutura de retorno de chamada de várias camadas aninhadas, uma estrutura típica de pirâmide é formada aqui. Se a lógica de negócios for mais complicada, ela se tornará um inferno aterrorizante de retorno de chamada.
Se você tiver melhor consciência e sabe extrair funções simples, o código ficará assim:
var func1 = function () {setTimeout (func2, 2000);}; var func2 = function () {console.log ("log1"); setTimeout (func3, 3000);}; var func3 = function () {console.log ("log2"); setTimeout (func4, 4000);}; var func4 = function () {console.log ("log3");};Isso parece um pouco melhor, mas sempre parece um pouco estranho. . . Bem, na verdade, meu nível de JS é limitado, então não posso dizer por que não consigo escrever isso bem. Se você sabe por que isso não é bom e então você inventou a promessa, entre em contato.
Agora vamos voltar ao ponto e falar sobre a coisa da promessa.
Descrição da promessa
Permita -me citar a descrição da promessa de MDN aqui:
O objeto Promise é usado para cálculos diferidos e cálculos assíncronos. Um objeto de promessa representa uma operação que não foi concluída, mas deve ser concluída no futuro.
O objeto Promise é um proxy para o valor de retorno, que pode não ser conhecido quando o objeto Promise é criado. Ele permite especificar um método de manuseio para sucesso ou falha de uma operação assíncrona. Isso permite que um método assíncrono retorne um valor como um método síncrono: o método assíncrono retorna um objeto de promessa que contém o valor de retorno original em vez do valor de retorno original.
O objeto Promise tem os seguintes estados:
• Pendente: estado inicial, não cheio ou rejeitado.
• Realizado: operação bem -sucedida.
• Rejeitado: Operação com falha.
O objeto Promise com um estado pendente pode ser convertido em um estado cumprido com um valor de sucesso ou um estado rejeitado com uma mensagem de falha. Quando o Estado for transmitido, o método vinculado a promessa. Então (identificador de função) será chamado. (Ao vincular um método, se o objeto de promessa já estiver no estado cumprido ou rejeitado, o método correspondente será chamado imediatamente; portanto, não há condição de corrida entre a conclusão da operação assíncrona e seu método de ligação.)
Para obter mais descrições e exemplos de promessa, consulte a entrada da promessa do MDN ou a entrada da promessa do MSDN.
Tente resolver nosso problema com promessa
Com base no entendimento acima da promessa, sabemos que podemos usá-lo para resolver o problema que o código por trás do retorno de chamada de várias camadas aninhadas é estúpido e difícil de manter. Os dois links dados acima já estão muito claros sobre a sintaxe e os parâmetros da promessa. Não vou repeti -los aqui, basta fazer o upload do código.
Vamos primeiro tentar um caso relativamente simples, que executa apenas atrasos e retornos de chamada uma vez:
nova promessa (function (res, rej) {console.log (date.now () + "start setTimeout"); setTimeout (res, 2000);}).Parece que não há diferença nos exemplos no MSDN, e o resultado da execução é o seguinte:
$ node promissor.js1450194136374 Iniciar o setTimeout1450194138391 Ligue para o tempo limite
Então, se quisermos fazer outro atraso, posso escrever isso:
nova promessa (function (res, rej) {console.log (date.now () + "start settimeout 1"); setTimeout (res, 2000);}). Então (function () {console.log (date.now () + "timeout 1 ligue de volta"); newster (function (res,) (date.now) () () (); 3000);Parece funcionar corretamente também:
$ node promissest.js1450194338710 START Settimeout 11450194340720 Tempo limite 1 Ligue para Back1450194340720
Mas o código parece estúpido e fofo, certo? Está construindo vagamente uma pirâmide novamente. Isso vai contra o objetivo de introduzir promessas.
Então, qual é o problema? Qual é a postura correta?
A resposta está oculta no valor de retorno da função então e a função de retorno de chamada (ou onompletada) da função.
Primeiro de tudo, a função então retornará uma nova variável de promessa e você poderá chamar a função então dessa nova variável de promessa novamente, assim:
nova promessa (...). Então (...). Então (...). Então (...). Então (...). Então (...).
Que tipo de promes é devolvido pela função então depende do valor de retorno do retorno de chamada onfulfilled.
De fato, o Onfulfilled pode retornar uma variável normal ou outra variável de promessa.
Se o On Fulfilless retornar um valor normal, a função retornará uma variável de promessa padrão. A execução da função então dessa promessa fará com que a promessa satisfaça imediatamente, e a função de realização é executada, e o parâmetro de entrada complementado é o valor de retorno do Onfulfilled anterior.
Se o OnfulFilless retornar uma variável de promessa, essa variável prometora será usada como o valor de retorno da função então.
Os documentos no MDN e no MSDN não têm uma descrição positiva clara desta série de configurações para a função e a função de realização. Quanto ao documento oficial do ES6 ECMAScript 2015 (6ª edição, ECMA-262). . . Eu realmente não consigo entender meu nível. Se algum especialista puder explicar a descrição dos dois valores de retorno no documento oficial, deixe uma mensagem para obter conselhos! ! !
Portanto, o exposto acima é o meu jogo gratuito, e a organização do idioma é um pouco difícil de descrever. Você entenderá depois de ler o código.
Primeiro, o caso de retornar variáveis normais:
nova promessa (function (res, rej) {console.log (date.now () + "inicie o setTimeout 1"); setTimeout (res, 2000);}). Então (function () {console.log (date.now () + "timeout 1 ligue"); return 1024;}). (FUNCT (" });O resultado da execução do código acima é:
$ node promistest.js1450277122125 Start Settimeout 11450277124129 Tempo limite 1 Ligue para Back1450277124129 Last on Fulfilless Return 1024
É um pouco interessante, certo, mas essa não é a chave. A chave é que a função onfulfilled retorna uma variável de promessa, o que torna conveniente chamar vários processos assíncronos em sucessão. Por exemplo, podemos tentar fazer duas operações de atraso em sucessão:
nova promessa (function (res, rej) {console.log (date.now () + "iniciar o setTimeout 1"); setTimeout (res, 2000);}). 3000);Os resultados da execução são os seguintes:
$ node promistest.js1450277510275 Iniciar o setTimeout 11450277512276 Tempo limite 1 Ligue para BACK1450277512276 Start Settimeout 21450277515327 Timeout 2
Se você acha que isso não é nada ótimo, não é um problema fazê -lo mais algumas vezes:
nova promessa (function (res, rej) {console.log (date.now () + "iniciar o setTimeout 1"); setTimeout (res, 2000);}). 3000); Timeout 3 Chamada de volta "); retorne nova promessa (function (res, rej) {console.log (date.now () +" Inicie o setTimeout 4 "); setTimeout (res, 5000);});});}). Então (function () {console.log.low.now () +" timeout 4 chamadas retornando);};$ node promistest.js1450277902714 Iniciar o setTimeout 11450277904722 Tempo limite 1 Ligue para BACK1450277904724 START Settimeout 21450277907725 Timeout 2 Ligue para Back145027777777725 Settimeout 41450277916744 Tempo limite 4 Ligue de volta
Pode-se observar que várias funções de retorno de chamada atrasadas são organizadas de maneira ordenada, e não há uma estrutura popular semelhante à pirâmide. Embora o código chama processos assíncronos, parece que todos são compostos de processos síncronos. Esta é a promessa de benefício nos traz.
Se você tem o bom hábito de destilar o código detalhado em funções separadas, será ainda mais bonito:
função timeout1 () {retorna nova promessa (function (res, rej) {console.log (date.now () + "start timeout1"); setTimeout (res, 2000);});} função timeout2 () {return timeout2 ") (res, reject; timeout3 () {retorna nova promessa (function (res, rej) {console.log (date.now () + "timeout2"); setTimeout (res, 3000);});} função timeout3 () {return timeout3 (function); timeout4 () {retorne nova promessa (function (res, rej) {console.log (date.now () + "start timeout4"); setTimeout (res, 5000);});} timeout1 () .Then (timeout2) .Then (Timeout3) .Then (date). });$ node promistest.js1450278983342 Timeout de início
Em seguida, podemos continuar estudando o problema de aprovar os parâmetros recebidos da função onfulfilled.
Já sabemos que, se a função anterior e preenchida retornar um valor normal, esse valor será o parâmetro de entrada da função onfulfilled; Então, se o Onfulfilled Returs Return uma variável de promessa, de onde vem o parâmetro de entrada do Onfulfilled?
A resposta é que o parâmetro de entrada desta função de realização é o valor passado quando a função Resolve foi chamada na promessa anterior.
Eu não conseguia aceitar o salto por um tempo, certo? Vamos fazer bem.
Primeiro de tudo, qual é a promessa da função.Resolve? Usando a declaração de Zou Zou acima do MDN
Resolva um objeto de promessa com o valor do sucesso. Se o valor for continuado (então pode
Em suma, este é o retorno de chamada quando a chamada assíncrona é bem -sucedida.
Vamos dar uma olhada na aparência do retorno de chamada em uma interface assíncrona normal. Tome FS.Readfile (arquivo [, opções], retorno de chamada) no NodeJS, por exemplo. Seu exemplo típico de chamada é o seguinte
fs.readfile ('/etc/passwd', function (err, dados) {if (err) tiro err; console.log (dados);});Porque para a função FS.Readfile, bem -sucedida ou falhada, ele chamará o retorno da função de retorno de chamada, para que esse retorno de chamada aceite dois parâmetros, a saber, a descrição da exceção na falha err e os dados do resultado de retorno sobre o sucesso.
Então, se formos promissores para reconstruir este exemplo de arquivo de leitura, como devemos escrevê -lo?
Primeiro, encapsular a função FS.ReadFile:
function readfile (nome do arquivo) {retorna nova promessa (function (resolve, rejeite) {fs.readfile (nome do arquivo, function (err, dados) {if (err) {rejeit (err);} else {resolve (dados);}});});});}} {resolve (data);}});});});}} {O segundo é a chamada:
readfile ('thefile.txt'). Então (function (data) {console.log (data);}, function (err) {tiro err;});Imagine onde o conteúdo do arquivo geralmente é colocado na interface de chamada síncrona dos arquivos de leitura em outros idiomas? O valor de retorno da função está correto? A resposta acabou, qual é a entrada ginseng desta determinação? É o valor de retorno quando a chamada assíncrona é bem -sucedida.
Com esse conceito, não é difícil entender o "parâmetro de entrada da função onfulfilled é o valor passado ao chamar a função de resolução na promessa anterior". Porque a tarefa onfulfilled é processar o resultado depois que a chamada assíncrona anterior for bem -sucedida.
Infelizmente, finalmente se endireitou. . .
Resumir
Permita -me usar um pedaço de código para resumir os pontos -chave explicados neste artigo:
function calp1 () {console.log (date.now () + "start callp1"); retornar nova promessa (function (res, ring) {setTimeout (res, 2000);});} função callp2 () {console.log (date.now () + "start callp2"); retornar nova promessa (function (res, rejé) {setTimeout (function () {res ({arg1: 4, arg2: "arg2 value"});}, 3000);});} função callp3 (arg) {console.log (date.now ()) + "start callp3 com arg =" + arg); Return New Promise (function (res, rejé) {setTimeout (function () {res ("callp3");}, arg * 1000);});} callp1 (). Então (function () {console.log (date.now () + "callp1 return; = " + Json.stringify (ret)); return callp3 (ret.arg1);}). Então (function (ret) {console.log (date.now () +" callp3 retornar com ret value = " + ret);}) $ Node promistest.js1450191479575 Iniciar CallP11450191481597 Callp1 Return1450191481599 Iniciar Callp21450191484605 Callp2 Retornar com Ret Value = {"Arg1": 4, "ARG2" "205 "ARGR ARG. 41450191488610 Callp3 Return com Ret Value = Callp3A experiência de aprendizado simples acima de usar promessa para resolver chamadas assíncronas de várias camadas é todo o conteúdo que compartilho com você. Espero que você possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.