With this code, 1,3,2 goes to the console, but 1,2,3 needed. Tell me how to implement this with promises and callbacks. setTimeout in the b() function emulates a wait from the server.

 function a() { setTimeout(function() { console.log(3); }, b()) } function b() { console.log(1); setTimeout(function() { console.log(2); return 2000; }, 5000) } a(); 

  • If you are given an exhaustive answer, mark it as correct (the daw opposite the selected answer) - Mr. Black

3 answers 3

About what exactly your problem has already written in the neighboring answers. I will give a solution to the problem using Promises :

 function a() { return b().then(function(timeout) { return new Promise(function(resolve) { setTimeout(resolve, timeout); }); }).then(function() { console.log(3); }); } function b() { console.log(1); return (new Promise(function(resolve) { setTimeout(resolve, 5000); })).then(function() { console.log(2); return 2000; }); } a(); 

And here is a working example on JSFiddle.

If the initial set of functions is not essential, then everything can be made somewhat simpler:

 (new Promise(function(resolve) { // Получаем данные с сервера console.log(1); setTimeout(function() { resolve(2000); }, 5000); })).then(function(timeout) { // Обрабатываем данные синхронно console.log(2); return timeout + 1; }).then(function(timeout) { // Обрабатываем данные аснихронно. return new Promise(function(resolve) { setTimeout(function() { resolve('Foo-Bar-Baz'); }, timeout); }); }).then(function(data) { // Выводим данные console.log(3); console.log(data); }); 
  • and why on JSFiddle? Immediately now there is all his own and even better, immediately shows the console. By the way, it seems to me that you did not quite understand the author, the essence of the question was to emulate a response from the server, that is, 1 is a request, 2 is an answer, 3 is work with the received data. That is, the largest gap should be between 1 and 2, and then immediately work out 3. - MasterAlex
  • so you wrapped :-) - Grundy
  • @MasterAlex, answer updated. now the gaps are really between pins. As for the local editor, I don’t like him. Well, the working example itself is, in fact, secondary. - Dmitriy Simushev
  • @Grundy, what? - Dmitriy Simushev
  • @DmitriySimushev, promise in timeout returning timeout for promise with timeout :-D - Grundy

Set the timer event series

1. What is the mistake

In your code, the a() function sets a timer based on the value obtained from the b() function. But b() returns nothing, because the string with return 2000; It appeared in function function() which is caused by the timer. Because of this, a() tries to set its timer to undefined and the console.log(3); command console.log(3); performed right there without a pause.


2. If you set the timers, starting with the first

We start the next timer after the previous one runs.

Your code could be:

 a(); function a() { console.log(1); setTimeout(function() { b(); }, 5000 ); } function b() { console.log(2); setTimeout(function() { c(); }, 2000 ); } function c() { console.log(3); } 

In general, you can:

 var delays = [ 5000, 4000, 3000, 2000 ]; delayConsole(0); function delayConsole( i ) { if( i < delays.length ) { console.log( (i+1) + '. ' + delays[i] ); setTimeout(function() { delayConsole( i+1 ) }, delays[i] ); } else { console.log( 'the end' ); }; } 


3. If you set timers, starting with the last

All timers run immediately. To start the next timer, the function summarizes all the delays that precede it.

Your code could be:

 a(); function a() { setTimeout(function() { console.log(3); }, 2000 + b() ); } function b() { var delayB = 5000; setTimeout(function() { console.log(2); }, delayB + c() ); return delayB; } function c() { console.log(1); return 0; } 

In general, you can:

 var delays = [ 5000, 4000, 3000, 2000 ]; delayConsoleBackward( delays.length ); function delayConsoleBackward( i ) { if( i > 0 ) { var sumDelay = delayConsoleBackward( i-1 ) + delays[i-1]; setTimeout(function() { console.log( ( i < delays.length ? i+1 : 'the end' ) + ' is after ' + sumDelay ); }, sumDelay); return sumDelay; } else { console.log( 1 ); return 0; }; } 

    callback

     // data(1, function(e) {console.log(e)}); data(1, e => console.log(e)); function data(i, callback) { console.log(i); setTimeout(function() { console.log(2); setTimeout(function() {callback(3);}, 2000); }, 5000); } 

    crutch

     a(); function a(s) { if(s == undefined) {b(); return;} setTimeout(function() { console.log(3); }, s); } function b() { console.log(1); setTimeout(function() { console.log(2); a(500); }, 1000); } 
    • The crutch turned out, but it seems to work - Mr. Black
    • it works, but how is it right? - HelpaMnePlz
    • @HelpaMnePlz, added an example with callback - Mr. Black