Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

237
Vistas
¿Cómo puedo encadenar funciones de forma asíncrona usando JavaScript?

Me pidieron que creara un objeto llamado foo que pudiera encadenar el log funciones y wait .

Por ejemplo:

 foo.log('breakfast').wait(3000).log('lunch').wait(3000).log('dinner');

En este escenario, primero imprime el breakfast , espera 3 segundos, imprime el lunch y luego, después de 3 segundos, imprime la dinner .

Intenté algo como esto, pero no funciona. ¿Qué me perdí?

 var foo = { log: function(text){ console.log(text); return foo; }, wait: function(time) { setTimeout(function() { return foo; }, time); } } foo.log('breakfast').wait(3000).log('lunch').wait(3000).log('dinner');

over 4 years ago · Santiago Trujillo
6 Respuestas
Responde la pregunta

0

Siempre es mejor usar promesas. Una implementación de esta funcionalidad podría ser;

 class Foo { constructor(){ this.promise = Promise.resolve(); } log(txt){ this.promise = this.promise.then(_ => console.log(txt)) return this; } wait(ms){ this.promise = this.promise.then(_ => new Promise(v => setTimeout(v,ms))); return this; } } var foo = new Foo(); foo.log("happy").wait(1000).log("new").wait(1000).log("year");

over 4 years ago · Santiago Trujillo Denunciar

0

Coloque la llamada a wait dentro de la anterior, y como último elemento, como una función recursiva.

 meals=['breakfast','elevenses','lunch','afternoon tea','dinner','supper']; c=0; wait=t=>{setTimeout(function() { if (c<meals.length) document.write(meals[c++],'<br>');wait(500); }, t);} wait(500);

over 4 years ago · Santiago Trujillo Denunciar

0

Para que conste, la excelente respuesta de Redu sin el azúcar de clase .

Ver también

 const foo = { promise: Promise.resolve(), log(txt) { this.promise.then(_ => console.log(txt)); return this; }, wait(ms) { this.promise = this.promise.then(_ => new Promise(v => setTimeout(v, ms))); return this; } }; // OR const Foo = (defaultMs = 1000) => { let promised = Promise.resolve(); return { log(txt) { promised.then(_ => console.log(txt)); return this; }, wait: function(ms) { promised = promised.then( _=> new Promise( rs => setTimeout(rs, ms || defaultMs) ) ); return this; } }; }; foo.log("Happy").wait(1000).log("new").wait(1000).log("year"); Foo().wait(3000) .log(`** From Foo ;)`).log(`Happy`).wait().log("new").wait().log("year");

over 4 years ago · Santiago Trujillo Denunciar

0

Más corto, dentro de Promise (no recomendado).

 Promise.prototype.log = function(txt) { return this.then(() => console.log(txt)) } Promise.prototype.wait = function(ms) { return this.then(() => new Promise(res => setTimeout(res, ms))) } var foo = Promise.resolve() foo.log('breakfast').wait(3000).log('lunch').wait(3000).log('dinner')
over 4 years ago · Santiago Trujillo Denunciar

0

Puedes hacerlo sin promesas:

 const foo = { log(text) { return {...foo, start: () => { this.start(); console.log(text); }}; }, wait(time) { return {...foo, start: () => { setTimeout(this.start, time); }}; }, start() {} }; foo.log('breakfast').wait(3000).log('lunch').wait(3000).log('dinner').start();
Las funciones foo.log() y foo.wait() regresan inmediatamente, devolviendo un clon modificado de foo . Se crea un clon usando {...foo} , pero con la función start() modificada para que llame a this.start() de la persona que llama seguido de la nueva operación. Cuando la cadena está completa, llama a start() para iniciar las acciones.

over 4 years ago · Santiago Trujillo Denunciar

0

Me inspiré en la solución de @James, que es parcialmente incorrecta porque los mensajes de registro están en el orden inverso, pero él no usa Promise s. Sigo pensando que la solución de @Redu debería ser la aceptada (después de todo, si puedes usar Promise s, eso es perfecto), pero esta también es interesante en mi opinión:

 const foo1 = { incrementalTimeout: 0, nextActions: [], log(text) { const textLog = () => { console.log(text); }; if (this.incrementalTimeout == 0) textLog(); else this.nextActions.push(textLog); return this; }, wait(time) { let newObj = {...this, incrementalTimeout: this.incrementalTimeout + time, nextActions: []}; setTimeout(() => { newObj.nextActions.forEach((action) => action()); } , newObj.incrementalTimeout); return newObj; } } foo1.log('breakfast').wait(1000).log('lunch').wait(3000).log('dinner');

La idea es que no registre el text de inmediato, sino que push una lambda con console.log en una matriz que se llamará después de que expire el tiempo de espera correcto.

Ejecuto todas las operaciones de log y wait una tras otra, pero llevo un registro de los segundos de espera antes de ejecutar las acciones. Cada vez que se llama a una nueva wait , el tiempo de espera incrementalTimeout se incrementa en time . Para mantener separadas las nextActions que pertenecen a diferentes períodos de tiempo, devuelvo un newObj cada vez, más o menos como lo hace @James.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda