w3schools then sincronas promises promesas nodejs funciones example catch anidadas javascript promise es6-promise

javascript - then - Creando una promesa(ES6) sin comenzar a resolverla



promise typescript (3)

Usando las promesas de ES6, ¿cómo creo una promesa sin definir la lógica para resolverla? Aquí hay un ejemplo básico (algo de TypeScript):

var promises = {}; function waitFor(key: string): Promise<any> { if (key in promises) { return promises[key]; } var promise = new Promise(resolve => { // But I don''t want to try resolving anything here :( }); promises[key] = promise; return promise; } function resolveWith(key: string, value: any): void { promises[key].resolve(value); // Not valid :( }

Se hace fácilmente con otras bibliotecas de promesas. JQuery es, por ejemplo:

var deferreds = {}; function waitFor(key: string): Promise<any> { if (key in promises) { return deferreds[key].promise(); } var def = $.Deferred(); deferreds[key] = def; return def.promise(); } function resolveWith(key: string, value: any): void { deferreds[key].resolve(value); }

La única forma en que puedo ver esto es almacenar la función de resolución en algún lugar dentro del ejecutor de la promesa, pero eso parece desordenado, y no estoy seguro de que esté definido exactamente cuando se ejecuta esta función. ¿Siempre se ejecuta inmediatamente en la construcción?

Gracias.


¡Buena pregunta!

El resolvedor pasado al constructor de la promesa se ejecuta de forma intencionada sincrónica para admitir este caso de uso:

var deferreds = []; var p = new Promise(function(resolve, reject){ deferreds.push({resolve: resolve, reject: reject}); });

Luego, en algún momento posterior en el tiempo:

deferreds[0].resolve("Hello"); // resolve the promise with "Hello"

La razón por la cual el constructor de la promesa se da es que:

  • Típicamente (pero no siempre) la lógica de resolución está ligada a la creación.
  • El constructor de la promesa es seguro y convierte las excepciones en rechazos.

A veces no encaja y para eso el resolver se ejecuta sincrónicamente. Aquí hay una lectura relacionada sobre el tema .


¿Qué tal un enfoque más integral?

Podría escribir un Constructor que devuelva una nueva Promesa decorada con .resolve() y .reject() .

Probablemente elegirías Deferred nombre al constructor Deferred , un término con mucha precedencia en [la historia de] las promesas javascript.

function Deferred(fn) { fn = fn || function(){}; var resolve_, reject_; var promise = new Promise(function(resolve, reject) { resolve_ = resolve; reject_ = reject; fn(resolve, reject); }); promise.resolve = function(val) { (val === undefined) ? resolve_() : resolve_(val); return promise;//for chainability } promise.reject = function(reason) { (reason === undefined) ? reject_() : reject_(reason); return promise;//for chainability } promise.promise = function() { return promise.then(); //to derive an undecorated promise (expensive but simple). } return promise; }

Al devolver una promsie decorada en lugar de un objeto simple, todos los métodos / propiedades naturales de la promesa permanecen disponibles, además de las decoraciones.

Además, al manejar fn , el patrón revelador permanece disponible, si necesita / elige usarlo en un Deferred.

DEMO

Ahora, con la utilidad Deferred() en su lugar, su código es prácticamente idéntico al ejemplo de jQuery.

var deferreds = {}; function waitFor(key: string): Promise<any> { if (key in promises) { return deferreds[key].promise(); } var def = Deferred(); deferreds[key] = def; return def.promise(); }


Quiero agregar mis 2 centavos aquí. Teniendo en cuenta exactamente la pregunta " Creando una promesa es6 sin comenzar a resolverla ", la resolví creando una función envoltorio y llamando a la función envoltorio en su lugar. Código:

Digamos que tenemos una función f que devuelve una Promesa

/** @return Promise<any> */ function f(args) { return new Promise(....) } // calling f() f(''hello'', 42).then((response) => { ... })

Ahora, quiero preparar una llamada a f(''hello'', 42) sin resolverla en realidad:

const task = () => f(''hello'', 42) // not calling it actually // later task().then((response) => { ... })

Espero que esto ayude a alguien :)

Promise.all() referencia a Promise.all() como se solicita en los comentarios (y respondida por @Joe Frambach), si quiero preparar una llamada a f1(''super'') y f2(''rainbow'') - 2 funciones que devuelven promesas -

function f1(args) { return new Promise( ... ) } function f2(args) { return new Promise( ... ) } const tasks = [ () => f1(''super''), () => f2(''rainbow'') ] // later Promise.all(tasks) .then(() => { ... })