JavaScript multiple ajax calls but can either be one or two I'm writing a piece of JavaScript to make one or two ajax calls. There will always be one ajax call fired but it might be two based on cookie setting. If user is logged in then we call another service to get the data. I would want this to fire async that's why I didn't put the second ajax call in the callback of the first call. We don't use jQuery just vanilla JS. 

'use strict';

import Cookie from 'js-cookie';
const _ = require('../helpers');

module.exports = function(cb) {
  let number_of_calls = 1;
  window._g = window._g || {};

  const uid = Cookie.get('uid');
  if (uid) {
    number_of_calls += 1;
  }

  function setG(fds) {
    --number_of_calls;
    const out = JSON.parse(fds);
    window._g.context = out;

    if (number_of_calls === 0) {
      cb({});
    }
  };

  function setUser(user) {
    --number_of_calls;
    const out = JSON.parse(user);
    window._g.user = out;
    if (number_of_calls === 0) {
      cb({});
    }
  }

  _.ajax({url: '//some_service/content?url=' + _.url}).done(setG);

  if (uid) {
    _.ajax({url: '//another_service/user?uid=' + uid}).done(setUser);
  } 
};
As mentioned in the comments, JS uses camelCase. Even if your team suggests to use snake_case consistently, JavaScript APIs are all in camelCase making your code look weird and out of place.



'use strict';

import Cookie from 'js-cookie';
const _ = require('../helpers');


Be consistent and use one module system. Suggesting you stick to the ES6 syntax as it is the standard.

Also, ES6 modules are in strict mode by default. This means the 'use strict'; pragma is unnecessary. If you're using a bundler that follows standards, it should be putting the pragma for you so you don't have to. If it doesn't put it for you, use a better bundler.



import Cookie from 'js-cookie';
const _ = require('../helpers');
module.exports = function(cb) {...}


Since I recommend writing ES6, then this should now be

import Cookie from 'js-cookie';
import _ from '../helpers';

export default function(cb){...}


_ and cb are not good names. Give them a full name, like Helpers and callback, respectively. "Lesser keystrokes" is not a good excuse. It's not worth the hassle debugging and you'll only lose hair faster.

Also, I would suggest ditching the callback pattern in favor of returning Promises. It will still look like callbacks when used, but it provides better control flow than callbacks.



window._g = window._g || {};


If  windows._g is just a temporary storage for your function's results, then as mentioned earlier, use promises. With promises, you can retrieve and pass on results from async operations without ever needing a temporary variable to store the data. The promise holds the values for you.




  multiple ajax calls but can either be one or two


Assuming _.ajax is not jQuery.ajax and the fact that you're using a done and not then, then _.ajax might not be returning promise-like objects. I suggest you do return a promise for _.ajax because what you're essentially doing is what Promise.all is for. It accepts multiple promises, and resolves when all are in. Good for multiple, parallel AJAX calls.

In the case of your second call, which is dependent on uid, you either return the _.ajax call promise or return a pre-resolved promise using Promise.resolve.



If I were to rewrite this module, it would look like this:

// getSessionData.js

import Cookie from 'js-cookie';
import Helpers from '../helpers';

export default function(){

  // Execute both requests. However, if `uid` isn't present, `userDataRequest`
  // will immediately be a resolved promise instead of a promise of an ajax call.
  const contextRequest = Helpers.ajax({});
  const userDataRequest = Cookie.get('uid') ? Helpers.ajax({}) : Promise.resolve({});

  // Wait for both promises to resolve. If `userDataRequest` is the pre-resolved
  // promise, then we'll only be waiting for `contextRequest`.
  //
  // This will resolve to { context: {}, user: {} }
  return Promise.all([contextRequest, userDataRequest])
                .then(([context, user]) =&gt; { context, user });
}

// Usage

import getSessionData from './getSessionData';

const sessionData = getSessionData().then(sessionData =&gt; {
  // This serves as replacement to your "callback"

  const context = sessionData.context;

  // user can either be the result from the AJAX call or a blank object.
  const user = sessionData.user;

  // Do stuff with context and user
});