Asynchronous code to synchronous built-in

    So, not so long ago, I had to face the rather popular task of converting asynchronous code to synchronous as part of a loop. In my case, it was working with the AmazonAPI productSearch methods. Everything would be fine, but this API just doesn’t like it when it is accessed too often, and I needed to interrogate the status of products in a cycle.

    In this article, I will use a practical example to talk about the implementation of the method that I used to solve my problem. Let's get started.

    For implementation we will need: promises (I will use the q library), nodejs version with generator support, experimental asynchronous function (we will use setTimeout).

    var q = require("q");
    function* itemGenerator(data)
    {
      var i, len = data.length;
      for(i = 0; i < len; i++)
      {
        yield data[i];
      }
    }
    function oldIterator(data)
    {
      var i = -1, len = data.length;
      return {
        "next": function()
        {
          i++;
          return {
            "done": i == len,
            "value": data[i]
          };
        }
      }
    }
    function main()
    {
      var def = q.defer(), items = [1, 2, 3, 4, 5];
      (function foo(gen)
      {
        var genItem = gen.next(), item = genItem.value;
        if(genItem.done)
        {
          def.resolve(true);
          return;
        }
        console.log("start call for", item);
        setTimeout(function()
        {
          console.log("end call for", item);
          foo(gen);
        });
      })(itemGenerator(items))
      return def.promise;
    }
    main().then(function(flag)
    {
      console.log("promise has been resolved", flag);
    });
    

    The result of this script will be:

    > node async_sync.js
    start call for 1
    end call for 1
    start call for 2
    end call for 2
    start call for 3
    end call for 3
    start call for 4
    end call for 4
    start call for 5
    end call for 5
    promise has been resolved true
    

    As we see, all of our asynchronous calls go in synchronous mode. To support older versions (not supporting generators), I added the “oldIterator” function, which will work similarly to a generator.

    PS : this code will work similarly in JavaScript, it’s enough to replace the “Q” library with the native “Promise”.

    That's all, thanks for watching!

    Also popular now: