First, the implementation of getReservedEntityId()
needs to make correct use of promises. I recommend a thorough reading of how promises work. In particular, it's important to understand that when your function performs an asynchronous task, you need to return a promise that will either resolve or reject based on the result of the asynchronous task.
function getReservedEntityId(collectionName) {
if (haveCachedIds) {
return Promise.resolve(cachedId);
} else {
return new Promise((resolve, reject) => {
// Make the AJAX call and call resolve(newId) in the success callback
// or call reject(errCode) in the failure callback.
// The arguments newId and errCode can be any values you like and are
// the values that get passed to the next link in the promise chain
// i.e. the values passed to then() or catch()
});
}
}
With that squared away, there are two recommended ways to make the calls synchronous:
1) Utilize a promise chain
getReservedEntityId(collectionName)
.then((id) => {
// Probably want to do something with `id` first...
return getReservedEntityId(collectionName);
})
.then( ... )
.then( ... );
Of course, if you're going to pass the same function to each .then()
call, you could just as well declare it as a regular function so as to not repeat yourself.
2) Using async/await
This is a new ES2017 feature and is still not widely supported. As of the time of this writing, Node.js supports async/await with the --harmony
flag, but most browsers do not. That said, async/await is intended for this exact purpose, treating functions returning promises as though they were synchronous. If you want to start using async/await in your code now, it is common practice to use JavaScript transpilers which which transpile your future-ready JavaScript to code that is supported by all major browsers.
This is how you would use async/await:
(async function someAsyncFunction {
const id1 = await getReservedEntityId(collectionName);
const id2 = await getReservedEntityId(collectionName);
const id3 = await getReservedEntityId(collectionName);
.
.
.
})();
The syntax is much nicer and more readable than the promise chain because it's designed for this exact purpose. Note that I have made the function self-invoking here so that it matches your behavior without having to make an extra function call. But you can use and call a function defined with async function
just like any other function that returns a promise.