¡Prométeme que debo entender esta vez! Promesa (Snack pequeño asíncrono / espera, una mejor solución basada en Promise)

Promesa

Antes de la Promesa, manejamos una solicitud de red asíncrona, algo como esto:

// La solicitud representa una llamada de red asincrónica. 
// El resultado de la solicitud representa la respuesta a la solicitud de red. 
Solicitud 1 ( función (resultado de solicitud 1) { 
    resultado de solicitud de proceso 1 
})

Se ve bastante bien.
Sin embargo, los requisitos han cambiado, necesitamos ejecutar la segunda solicitud de red en función del resultado de la primera solicitud de red, el código es probablemente el siguiente:

Solicitud 1 ( función (resultado de solicitud 1) { 
    Solicitud 2 ( función (resultado de solicitud 2) { 
        resultado de solicitud de proceso 2 
    }) 
})

No se ve complicado.
Pero . La demanda es infinita, por lo que aparece el siguiente código:

Solicitud 1 ( función (Resultado de solicitud 1) { 
    Solicitud 2 ( función (Resultado de solicitud 2) { 
        Solicitud 3 ( función (Resultado de solicitud 3) { 
            Solicitud 4 ( función (Resultado de solicitud 4) { 
                Solicitud 5 ( función (Resultado de solicitud 5) { 
                    Solicitud 6 ( función (Resultado de solicitud 3) { 
                        ... 
                    }) 
                }) 
            }) 
        }) 
    }) 
})

Esta vez atónito. . . El infierno de devolución de llamadas apareció.

Lo que es peor, básicamente tenemos que lidiar con los resultados de cada solicitud, el código estará más hinchado, en un equipo, la revisión del código y el mantenimiento posterior será un proceso muy doloroso.

Los efectos negativos del infierno de devolución de llamada son los siguientes:

  • El código está hinchado.
  • Poca legibilidad.
  • El acoplamiento es demasiado alto y la mantenibilidad es pobre.
  • La reutilización del código es deficiente.
  • Es fácil criar insectos.
  • Las excepciones solo se pueden manejar en devoluciones de llamada.

Cuando algo sale mal, alguien naturalmente encontrará un camino. En este momento, algunas personas pensaron, ¿podemos usar una organización de código más amigable para resolver el problema del anidamiento asincrónico?

deje que solicite el resultado 1 = solicite 1 (); 
deje que solicite el resultado 2 = solicite 2 (solicite el resultado 1); 
deje que solicite el resultado 3 = solicite 3 (solicite el resultado 2); 
deje que solicite el resultado 4 = solicite 2 (solicite el resultado 3); 
deje Solicitar resultado 5 = Solicitud 3 (Solicitar resultado 4);

Escritura sincrónica similar a la anterior. Así nació la especificación Promise, y hay muchas implementaciones en la industria para resolver los puntos débiles del infierno de devolución de llamadas. Por ejemplo, la famosa Q y bluebird de la industria, bluebird incluso afirman ser la biblioteca más rápida.

Que es una promesa

Promise es una solución para la programación asincrónica, que es más razonable y potente que las soluciones asincrónicas tradicionales [función de devolución de llamada] y [evento]. Ahora ha sido incorporado en la especificación por ES6.

Comparación de escritura de código

Todavía usando el ejemplo de solicitud de red anterior, echemos un vistazo a la forma convencional de escribir Promesas:

nueva promesa (solicitud 1) 
    .then (solicitud 2 (resultado de solicitud 1)) 
    .then (solicitud 3 (resultado de solicitud 2)) 
    .then (solicitud 4 (resultado de solicitud 3)) 
    .then (solicitud 5 (resultado de solicitud 4)) 
    . la captura (el procesamiento de excepciones (información de anomalía))

Compare esto con el estilo de devolución de llamada anterior. No es difícil encontrar que Promise está escrito de manera más intuitiva y puede captar información anormal de funciones asincrónicas en la capa externa.

API

Las promesas de las API de uso común son las siguientes:

  • Promise.resolve (valor)
Método de clase, este método devuelve un objeto Promesa analizado por el valor de valor
 1. Si el valor es un thenable (es decir, con el método then), el objeto Promise devuelto "seguirá" al objeto thenable, adoptando su estado final (en referencia a su estado final (en referencia a resuelto / rechazado / pendiente / resuelto) 
2. Si el valor pasado es un objeto Promise en sí, el objeto se devuelve como el valor de retorno del método Promise.resolve.
3. En otros casos, devuelva un objeto Promise con este valor como estado de éxito.

Lo anterior es la explicación del método de resolución: cuando se pasan diferentes tipos de valor, el resultado devuelto también es diferente. Esta API es más importante. Se recomienda que se familiarice con ella practicando algunos pequeños ejemplos y cooperando con la explicación anterior. Aquí hay algunos pequeños ejemplos:

// Si el valor pasado es en sí mismo un objeto Promise, el objeto se devuelve como el valor de retorno del método Promise.resolve.  
function fn (resolve) { 
    setTimeout ( function () { 
        resolve ( 123 ); 
    }, 3000 ); 
} 
let p0 = new Promise (fn); 
let p1 = Promise.resolve (p0);
 // Return to true, return Promesa es el objeto Promesa que ingresa el parámetro. 
console.log (p0 === p1);

Pase el objeto que se puede guardar y devuelva el objeto Promesa para seguir el estado final del objeto que se puede guardar.

El concepto de Thenable se menciona en ES6 Promises. En resumen, es una promesa muy similar. El ejemplo más simple es jQuery.ajax, y su valor de retorno es el objeto habilitable. 
Pero tenga en cuenta que no es necesario usarlo como un objeto Promise mientras se implemente el método.
// Si el valor pasado es en sí mismo un objeto que se puede guardar, el objeto de promesa devuelto seguirá el estado del objeto que se puede guardar. 
let promise = Promise.resolve ($. ajax ('/ test / test.json')); // => objeto de 
promesa promise.then ( function (value) { 
   console.log (value); 
});

Devuelve un objeto Promise cuyo estado se resolvió.

let p1 = Promise.resolve (123 ); 
 // Imprimir p1 Puede ver que p1 es un objeto Promise con el estado establecido en 
console.log resuelto (p1)
  • Promesa rechazo

Métodos de clase, y la única diferencia con la resolución es que se rechaza el estado del objeto de promesa devuelto.

  • Promise.prototype.then

Método de instancia, registre una función de devolución de llamada para Promise, forma de función: fn (vlaue) {}, el valor es el resultado devuelto de la tarea anterior, la función debe devolver un resultado o un nuevo objeto Promise, entonces solo entonces Recepción de devolución de llamada.

  • Promise.prototype.catch

Método de instancia, excepción de captura, forma de función: fn (err) {}, err es la información de excepción lanzada por la devolución de llamada antes del registro de captura.

  • Promise.race

En el método de clase, se ejecutan varias tareas de Promise al mismo tiempo, y se devuelve el resultado de la tarea de Promise que es la primera en ejecutarse, independientemente de si el resultado de Promise fue exitoso o fallido. .

  • Promesa.todos

Método de clase, múltiples tareas de Promise se ejecutan simultáneamente.
Si todos se ejecutan correctamente, los resultados de ejecución de todas las tareas de Promise se devuelven en una matriz. Si hay una tarea Promesa rechazada, solo se devuelve el resultado de la tarea rechazada.

  • ...

Lo anterior son las API de Promises que se usan comúnmente. Después de dominarlas, podemos usar Promesas de manera competente.

Asegúrese de practicar más y ser competente, de lo contrario se extenderá un medio conocimiento durante la entrevista.

Cómo entender las promesas

 

Para facilitar la comprensión de las promesas, además de una mayor práctica, la mejor manera es poder conectar el mecanismo de la promesa con ejemplos de la vida real, de modo que realmente se pueda digerir.

Podemos comparar Promise con una niñera, una serie de cosas en casa, solo necesita decirle, él puede ayudarlo a hacerlo, puede hacer otras cosas.
Por ejemplo, como cabeza de familia, tengo que salir a trabajar un día, pero todavía tengo que comprar comida y cocinar y enviarla a la unidad de mi esposa (entienda mi estado en casa ...)

Las cosas que hacer al salir son importantes, como lo es comprar comida y cocinar. Pero solo puedo hacer una cosa yo mismo.

En este momento, puedo darle a la niñera el trabajo de comprar comida y cocinar. Le diré:

  • Vas al supermercado a comprar comida primero.
  • Cocine con los platos comprados en el supermercado.
  • Envíe las comidas preparadas a la unidad de la esposa.
  • Llámame cuando llegues a la unidad.

Sabemos que los tres pasos anteriores requieren mucho tiempo, y podemos entenderlos como tres tareas asincrónicas. Use Promise para escribir esta operación:

función de compras (resolver, rechazar) { 
    setTimeout ( function () { 
        resolver ([ 'tomate', 'huevo', 'semilla oleaginosa' ]); 
    }, 3000 ) 
} 
función de cocinar (resolver, rechazar) { 
    setTimeout ( función ( ) {
         // El siguiente paso es procesar el arroz cocido. 
        Resolver ({ 
            Alimento principal: 'arroz' , 
            platos: [ 'huevos revueltos de tomate', 'violación clara frita' ] 
        }) 
    }, 3000 )) 
} 
función para enviar arroz (resolver , Rechazar) {
     // 
    Resolver ('Mi esposa da da' ) para el resultado de la entrega de comida 
} ; }
function call me () {
     // El siguiente paso después de llamarme, 
    agrega un bono de 100 yuanes a la niñera; 
}

Ok, ahora he resuelto cuatro tareas. En este momento, necesito decirle a la niñera y dejar que siga la lista de tareas.

Este proceso es esencial porque si no le dice a la niñera, la niñera no sabe lo que hay que hacer. . (Mi niñera es perezosa)

// Dígale a la niñera que me ayude a hacer algunas cosas coherentes, primero vaya al supermercado a comprar comida 
Promesa nueva ( comprar comida)
 // use la comida que compra para 
cocinar. Luego ((compra comida) => {
     devolver  nueva promesa (cocinar) ; 
}) 
// Enviar la comida preparada a la 
compañía de la esposa . Luego ((comida preparada) => {
     devolver una  nueva promesa (enviar comida); 
}) 
// Llamar y notificarme después de la 
comida. Resultados de entrega de comidas) => { 
    Llámame (); 
})

En este punto, le informé a la niñera que hiciera estas cosas, y luego puedo hacer mis cosas con seguridad.

Tenga en cuenta que si nuestra tarea de seguimiento es una tarea asincrónica, debemos devolver un nuevo objeto de promesa.
Si la tarea de seguimiento es una tarea síncrona, solo necesita devolver un resultado.
El ejemplo que dimos anteriormente, excepto que el teléfono me informa que es una tarea sincrónica, el resto son tareas asincrónicas y el retorno de la tarea asincrónica es el objeto de la promesa.

Además, debe recordarse que un objeto Promise tiene tres estados, y una vez que el estado cambia, no se puede cambiar a otros estados.

  • pendiente, la tarea asincrónica está en progreso.
  • resuelto (también llamado cumplido), la tarea asincrónica se ejecuta con éxito.
  • rechazado, la ejecución asincrónica de la tarea falló.

Resumen de uso de la promesa

Promise tiene tantos conceptos que es difícil para los principiantes digerirlo todo de una vez, por lo que podemos adoptar el método de memoria forzada para obligarnos a recordar el proceso de uso.

Primero inicialice un objeto Promise, que se puede crear de dos maneras, y ambas devolverán un objeto Promise.

  • 1 、 nueva promesa (fn)
  • 2 、 Promise.resolve (fn)

Luego llame al método then del objeto de promesa devuelto en el paso anterior para registrar la función de devolución de llamada.

  • La función de devolución de llamada en entonces puede tener un parámetro o ningún parámetro. Si la función de devolución de llamada en depende del resultado de retorno del paso anterior, entonces traiga los parámetros. Por ejemplo
    nueva promesa (fn) 
    .then (fn1 (valor) { 
        // 处理 valor 
    })
  • Finalmente, registre la función de manejo de excepciones de captura para manejar las excepciones que se pueden generar en la devolución de llamada anterior.

Por lo general, siga estos tres pasos, puede manejar la mayoría de los escenarios de procesamiento asíncrono. Después de familiarizarse con él, puede estudiar los principios más profundos y el uso de cada función Promise.

Después de ver esto, podemos responder las preguntas 4 y 5 anteriores.

Promsie y evento loop

Cuando se inicializa la Promesa, la función entrante se ejecuta sincrónicamente y luego se registra la devolución de llamada. Después del registro, continúe ejecutando el código de sincronización, antes de eso, la devolución de llamada no se ejecutará en ese momento.

Después de completar la ejecución del bloque de código síncrono, detectará si hay una devolución de llamada prometedora disponible en el bucle de eventos. Si es así, ejecútelo. Si no, continúe con el siguiente bucle de eventos.

Acerca de Promises También hay un concepto de microtask (microtask) en el bucle de eventos. Si está interesado, puede obtener más información. Aunque es ligeramente diferente del navegador, el tiempo de ejecución de Promise microtasks no es muy diferente.

Promesa de actualización asíncrona / espera

ES6 tiene un generador y una sintaxis asíncrona / en espera, lo que hace que el procesamiento asincrónico se acerque más a la escritura de código sincrónico y una mejor legibilidad. El ejemplo anterior se puede escribir así:

(async () => ( 
    dejar verduras = esperar para comprar verduras (); 
    dejar comidas = esperar para cocinar (verduras); 
    dejar resultados de entrega de comidas = esperar entrega de comidas (comidas); 
    dejar resultados de notificación = esperar notificarme (resultados de entrega de comidas) ; 
}) ();

¿Está más claro? Debe recordarse que async / await también se basa en Promises, por lo que aún necesitamos entender las Promesas en profundidad.

Supongo que te gusta

Origin www.cnblogs.com/magicg/p/12741988.html
Recomendado
Clasificación