1
\$\begingroup\$

I haven't really worked much with asynchronous code so I'm wondering if I am doing something wrong/something could go wrong. Right now of all the test cases that I have done, my code has worked but I'm not sure if I will get side effects or not.

I won't post any of the business logic, just the iteration part with the asynchronous function in it:

function asyncInIteration(skinArray)  {
   request("/someaddresshere", function (err, response, data)  {

      var left = something.length;

      for (var i = 0;i<something.length;i++) (function (i) {
          request("/someotheraddress", function (err, response, data) {
             if (--left === 0)  {
                 console.log("End of for loop");
             }
          })
      })(i);
   });
}

Basically, what I am trying to do with this code is loop through an array (skinArray) and add values to it via sending HTTP requests.

The most important thing for me is that:

  1. Every value of i should only be repeated once.
  2. When I call --left === 0, that has to be called once, and only after all values of i have been gone through.

If someone wants to see the code with the business logic, you can find it here.

\$\endgroup\$
3
  • \$\begingroup\$ This will properly detect when the last request() operation finishes. Do you need the request() results in order when you're done? Are you OK with all the request() operations being launch in parallel (all in-flight at the same time)? \$\endgroup\$
    – jfriend00
    Commented Mar 9, 2016 at 5:54
  • \$\begingroup\$ Yeah I don't mind if they aren't in order. The only thing that matters for me is that everything in the array only iterates once and the --left === 0 conditional is at the end of the for loop. \$\endgroup\$
    – mre12345
    Commented Mar 9, 2016 at 7:48
  • \$\begingroup\$ Your wording makes me wonder if you understand the actual sequence of events here. First, your for loop runs and initiates all the requests. At that point, the for loop is done and any code that comes after it executes. Then, some time later the first request() finishes and calls its callback. Then, sometime later, the next does. Then, finally the last one completes and your left variable will hit 0. The for loop was done long before this. \$\endgroup\$
    – jfriend00
    Commented Mar 9, 2016 at 7:50

1 Answer 1

1
\$\begingroup\$

Use lodash to make Your iteration "readable".

And use async to handle end of asynchronous iteration to properly respond with "end of loop"

var _ = require('lodash');

var something = ['a','b','c'];
function asyncInIteration(skinArray)  {

   request("/someaddresshere", function (err, response, data)  {
      var functions = []; // array of functions that will be called

      // generating array of functions
      _.times(something.length, 
          function() {
              // pushing function to functions list
              functions.push(function(done){ // "next" is necessary to inform async module about finishing call
                  request("/someotheraddress", function (err, response, data) {
                      // doing something
                      console.log("\n--------");
                      console.log("RESPONSE:", data);
                      console.log("--------\n");
                      done();
                  });
              });
          });

      // can change to .series if You want to make it synchronous (not parallel)
      async.parallel(functions, function(){
          console.log('End of loop');
      });
   });
}

P.S. In fact my code looks like not so simple, but there is no another elegant way to control asynchronousity. Maybe Promise object will be easy to work, but I don't think it's suitable for current task.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.