My task is to perform several asynchronous processes in angularjs sequentially. Their number is not known in advance.
As an example: the path is passed to the procedure and you need to create all the folders sequentially, since The next folder can only be created in the previous one. In this case, you need to wait for completion.
I did this through the recursive _manager call, the procedure works, but does not report the completion to start.

 .factory('TEST_F', function ($timeout, $q) { var isStop = false; var stop = function () { isStop = true; console.log('stop loop'); }; var start = function () { console.log('start loop'); isStop = false; var i = 0; _manager(i) .then(function (data) { console.log('---> resolve, i = ' + data.i); }, function (data) { console.log('---> reject, i = ' + data.i); }); }; var _manager = function (i) { var deferred = $q.defer(); _doer() .then(function (data) { i++; console.log('isStop = ' + isStop, 'i = ' + i); if (data.state === 'ok' && !isStop) { //deferred.resolve({state: 'ok', i: i}); return _manager(i); } else { deferred.reject({state: 'error', i: i}); return {state: 'error', i: i}; } }, function (data) { deferred.reject({state: 'error', i: i}); return {state: 'error', i: i}; }); return deferred.promise; }; var _doer = function () { var deferred = $q.defer(); $timeout(function () { console.log('loop'); }, 2000) .then(function (data) { console.log('+2 sec'); deferred.resolve({state: 'ok'}); }) ; return deferred.promise; }; return { stop: stop, start: start } }) 

Tell me please, how can you implement the sequential execution of asynchronous procedures?

  • And why in _manager string deferred.resolve({state: 'ok', i: i}); commented out? - Regent
  • Because the promise will return the next line. - DenniLa2 pm
  • one
    And what's the point of promising if you do not fulfill your promises ( .resolve() ) anywhere? In this case, you need to pass the deferred object to recursive function calls and do .resolve() in the last one. return inside a function in .then() useless. - Regent
  • If, judging by the code, the last _manager() should always do .reject() , then the problem is that .reject() is done for deferred from the last _manager() , and not from the first, while start() waiting for the result of the first deferred . - Regent

2 answers 2

@Regent, taken your tips and rewrote _manager.

 var _manager = function (i) {
       var deferred = $ q.defer (); 

_doer(i) .then(function (data) { i++; console.log('isStop = ' + isStop, 'i = ' + i); if (data.state === 'ok' && !isStop && i < 7) { // доп. условие остановки //deferred.resolve({state: 'ok', i: i}); return _manager(i); } else { //deferred.resolve({state: 'end', i: data.i}); return {state: 'end', i: data.i}; } }, function (data) { //deferred.reject({state: 'error', i: data.i}); return {state: 'error', i: data.i}; }) .then(function (data) { if(data.state === 'ok') { deferred.resolve({state: 'ok', i: data.i}); } else if (data.state === 'end') { deferred.resolve({state: 'end', i: data.i}); } else { deferred.resolve({state: 'error', i: data.i}); } }) ; return deferred.promise; };

Now everything works as I need. But it seems to me that it can be written somehow shorter.

  • Pain and suffering, especially with $q , but I still got fiddle to work. Now I will try to simplify the code. - Regent
  • @Regent, I wrote at the beginning of the post that I need to wait for the sequential execution of asynchronous requests, when their number is not known in advance. $ timeout () is used to simulate them. Such a need arose when creating subfolders on a mobile device (ionic) when I do not know in advance the depth of nesting and create all the way. Or when you need to send files one by one to the server. Of course, you could use $ q.all ([]), but in my particular case it was not exactly what I needed. - DenniLa2
  • Yes, sorry, while picking up the code, I already forgot what the question was about ... In general, I didn’t find any radical simplification of the code with the same functionality. Because of the need to use Promise and different answers in different situations, the code looks like this. - Regent
  • @Regent, thank you! - DenniLa2
  • On health. Although, in fact, almost not for that. Since your answer is a solution, you can mark it as correct. - Regent

You do not have a stop condition. Since i can grow indefinitely, nothing happens.

  • The stop condition is a call to the .stop() method somewhere in the external code. - Regent