javascript patterns

Finding A List of Objects Asynchronously In JavaScript

There are many libaries and functions to find asynchronous resources. But there are times when you just want to quickly get a bunch of pieces of data without going through the trouble of investigating and using multiple libraries. It is also useful to know how to easily get async resouces without libraries, since it shows the core idea of what libraries will do (though they should be much more optimized though). For the simplest strategy, the key is to apply recursion:

// Simulate an API call
function getCar(carName, callback) {
  const cars = {
    miata: { hp: 155, weight: 2400 },
    elise: { hp: 217, weight: 2000 },
    '4C': { hp: 237, weight: 2465 }
  };

  setTimeout(function() {
    callback(cars[carName]);
  }, 500);
};

function findAllCars(carNames, callback, index, cars) {
  index = index || 0;
  cars = cars || [];

  getCar(carNames[index], function(car) {
    cars.push(car);

    if (cars.length < carNames.length) {
      findAllCars(carNames, callback, index + 1, cars);
    } else {
      callback(cars);
    }
  });
};

const carNames = ['4C', 'miata', 'elise'];
findAllCars(carNames, function(cars) {
  console.log(cars);
  // [ { hp: 237, weight: 2465 },
  //   { hp: 155, weight: 2400 },
  //   { hp: 217, weight: 2000 } ]
});

The idea is that the item set (carNames) is iterated through by incrementing the index with the cars variable accumulating the results. Arguably, the length of cars could be used instead of index, but that makes the codes intention less clear and so less easy to adapt. This pattern can be used to extract any form of objects asynchronously easily and supports many variants with only tiny alterations. For example, in this case there are no dependencies between calls, so all the calls could be done at once. This is simple if order does not matter:

function findAllCarsOptimized(carNames, callback) {
  let index = 0,
    cars = [];

  carNames.forEach(function(carName) {
    getCar(carName, function(car) {
      cars.push(car);

      if (cars.length === carNames.length) {
        callback(cars);
      }
    });
  });
};

In other words, just iterate through each car and send a request. Recursion does not need to be done, so the callback condition is only needed. The rest of the structure remains the same. Which makes this a great strategy for prototyping anything asynchronous or doing code when Promises or libraries are not available/practical.

Github Location: https://github.com/Jacob-Friesen/obscurejs/blob/master/2017/findAsyncInOrder.js