w3schools then promises promesas promesa funciones example encadenar anidadas javascript jquery promise jquery-deferred deferred

then - promise javascript example



en JavaScript, ¿cómo envolver una promesa en el tiempo de espera? (3)

Es un patrón común para implementar el tiempo de espera de alguna función asíncrona, usando apfered / promise:

// Create a Deferred and return its Promise function timeout(funct, args, time) { var dfd = new jQuery.Deferred(); // execute asynchronous code funct.apply(null, args); // When the asynchronous code is completed, resolve the Deferred: dfd.resolve(''success''); setTimeout(function() { dfd.reject(''sorry''); }, time); return dfd.promise(); }

Ahora podemos ejecutar una función asíncrona llamada myFunc y manejar el tiempo de espera:

// Attach a done and fail handler for the asyncEvent $.when( timeout(myFunc, [some_args], 1000) ).then( function(status) { alert( status + '', things are going well'' ); }, function(status) { alert( status + '', you fail this time'' ); } );

OK, vamos a hacer un giro en esta historia! Imagine que el propio myFunc devuelve una promesa (NOTA: la promesa NO se aplaza y no puedo cambiarla):

function myFunc(){ var dfd = new jQuery.Deffered(); superImportantLibrary.doSomething(function(data)){ if(data.length < 5){ dfd.reject(''too few data''); } else{ dfd.resolve(''success!''); } }, {''error_callback'': function(){ dfd.reject("there was something wrong but it wasn''t timeout");} }}); return dfd.promise(); }

Ahora, si myFunc mi myFunc en el timeout de timeout , myFunc la capacidad de manejar los errores de manera diferente. Si myFunc emite eventos de progreso, también myFunc esto.

Entonces, la pregunta es: ¿cómo modificar la función de timeout para que pueda aceptar funciones que devuelven promesas sin perder sus errores / información de progreso?


Me doy cuenta de que esto tiene 2 años, pero en caso de que alguien esté buscando la respuesta ...

Creo que Benjamin estuvo cerca en que deseará que su tiempo de espera se maneje por separado, así que comenzaremos con su función de demora.

function delay(ms){ var d = $.Deferred(); setTimeout(function(){ d.resolve(); }, ms); return d.promise(); }

Luego, si desea esperar antes de que se ejecute el código, puede llamar al método que desea retrasar como resultado de esta promesa.

function timeout(funct, args, time) { return delay(time).then(function(){ // Execute asynchronous code and return its promise // instead of the delay promise. Using "when" should // ensure it will work for synchronous functions as well. return $.when(funct.apply(null, args)); }); }

Esto suele ser lo que trato de hacer cuando busco un repaso (por qué estoy aquí). Sin embargo, la pregunta no era sobre retrasar la ejecución, sino lanzar un error si demoraba demasiado. En ese caso, esto complica las cosas porque no quiere esperar el tiempo de espera si no tiene que hacerlo, por lo que no puede simplemente envolver las dos promesas en un "cuándo". Parece que necesitamos otro aplazado en la mezcla. (Consulte Esperar a que se resuelva el primero de los aplazados de jQuery múltiples ).

function timeout(funct, args, time) { var d = $.Deferred(); // Call the potentially async funct and hold onto it''s promise. var functPromise = $.when(funct.apply(null, args)); // pass the result of the funct to the master defer functPromise.always(function(){ d.resolve(functPromise) }); // reject the master defer if the timeout completes before // the functPromise resolves it one way or another delay(time).then(function(){ d.reject(''timeout''); }); // To make sure the functPromise gets used if it finishes // first, use "then" to return the original functPromise. return d.then(function(result){ return result; }); }

Podemos simplificar esto, sabiendo que, en este caso, el aplazamiento maestro solo rechaza si el tiempo de espera se produce primero y solo se resuelve si el compromiso de función se resuelve primero. Debido a esto, no tenemos que pasar la promesa de función a la resolución de aplazamiento principal, ya que es lo único que se podría pasar y todavía estamos dentro del alcance.

function timeout(funct, args, time) { var d = $.Deferred(); // Call the potentially async funct and hold onto it''s promise. var functPromise = $.when(funct.apply(null, args)) .always(d.resolve); // reject the master defer if the timeout completes before // the functPromise resolves it one way or another delay(time).then(function(){ d.reject(''timeout''); }); // To make sure the functPromise gets used if it finishes // first, use "then" to return the original functPromise. return d.then(function(){ return functPromise; }); }


Siempre debes promsiificar al nivel más bajo posible. Vamos a empezar desde lo básico.

Usaré las promesas de jQuery aquí, pero esto debería hacerse con una biblioteca más fuerte como Bluebird. Comencemos simple, creando nuestro delay como:

function delay(ms){ var d = $.Deferred(); setTimeout(function(){ d.resolve(); }, ms); return d.promise(); }

El retraso de la nota no hace nada sorprendente, toda nuestra función de retraso es causar un retraso de ms milisegundos.

Ahora, para su biblioteca, queremos crear una versión de doSomething que funcione con promesas:

superImportantLibrary.doSomethingAsync = function(){ var d = $.Deferred(); superImportantLibrary.doSomething(function(data){ d.resolve(data); }); return d.promise(); };

Tenga en cuenta que nuestras funciones de retraso y doSomethingAsync hacen una sola cosa . Ahora comienza la diversión.

function timeout(promise,ms){ var timeout = delay(ms); // your timeout var d = $.Deferred(); timeout.then(function(){ d.reject(new Error("Timed Out")); }); promise.then(function(data){ d.resolve(data); }); return d.promise(); } timeout(superImportantLibrary.doSomethingAsync(),1000).then(function(data){ // handle success of call }, function(err){ // handle timeout or API failure. });

Ahora en Bluebird, todo este código habría sido:

superImportantLibrary.doSomethingAsync().timeout(1000).then(function(){ // complete and did not time out. });


function timeout(funct, args, time) { var deferred = new jQuery.Deferred(), promise = funct.apply(null, args); if (promise) { $.when(promise) .done(deferred.resolve) .fail(deferred.reject) .progress(deferred.notify); } setTimeout(function() { deferred.reject(); }, time); return deferred.promise(); }