Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

234
Views
¿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 answers
Answer question

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 Report

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 Report

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 Report

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!