Talking Code: Using Native JavaScript (JS) Promise (also in Axway Titanium)

Eswar Jayavarapu | September 5, 2018 | Mobile App Development

Now that ES6 support is available in Axway Titanium SDK, you may start using Native JavaScript (JS) Promise (also in Axway Titanium) in your code to build applications. What this means is you can now avoid callback hell while making asynchronous calls through Promise.

Using Promise in Axway Titanium is similar to its implementation anywhere else. Until I started using Promises in my code, I didn’t realize how much they help keep code clean while making it more maintainable. With the help of Promises, you no longer need to worry about organizing code—especially when making multiple calls, either synchronously or asynchronously. But before we get into implementation, lets review some basics and some terminology.

What is Promise
Promise is a JavaScript object that acts as a proxy to a value that may (or may not) be available yet but will be available at some point in future.

A Promise can be in one of the following 3 possible states:

  • Pending – Initial state
  • Fulfilled – Successfully completed
  • Rejected – Failed
  • Settled – Either Fulfilled or Rejected

Syntax:

var promise = new Promise(function(_resolve, _reject) {
// Executor function
});

As shown in the above syntax, Promise object takes a function as an argument called Executor function which will be executed immediately when the Promise is constructed. It takes two callback functions as input params: resolve and reject. The executor function can call either resolve or reject which will update the Promise status as Settled (Fulfilled/Rejected).

Now let’s simulate an asynchronous operation (can be a service call to a server or an event listener) using setTimeout.

Example:

function wait(_waitTime) {
return new Promise(function(_resolve, _reject) {
setTimeout(function() {
_resolve('Resolved in ' + _waitTime/1000 + 'second(s).');
}, _waitTime);
});
}

The wait method in the above example returns a promise which will be resolved in waitTime number of milliseconds. But, how to use this promise to know when it’s resolved? We use .then to handle our action when the promise is resolved.

wait(1000).then(function(_result) {
console.log(_result);
// Resolved in 1 second(s).
});

.then here will be called when the promise returned by wait is resolved, which will make the above piece of code print the result in one second(1000ms);

Now we know how to know when the promise is resolved. How do we know when the promise is rejected? Similar to .then, we use .catch to find when the promise is rejected.

function wait(_waitTime) {
return new Promise(function(_resolve, _reject) {
(_waitTime >= 5000) && _reject('Rejected wait time ' + _waitTime/1000 + 'seconds.');
setTimeout(function() {
_resolve('Resolved in ' + _waitTime/1000 + 'second(s).');
}, _waitTime);
});
}

wait(5000).then(function(_result) {
console.log(_result);
})
.catch(function(_error) {
console.log(_error)
// Rejected wait time 5 seconds.
});

I modified the previous example to reject the promise when the wait time is greater than or equal to 5000(ms). Hence, the promise returned by wait in this example will be rejected immediately, which will make the .catch execute immediately and print Rejected wait time 5 seconds.. .catch will be called even if any error is thrown by the executor function.

If you observe the above example, you’ll notice there’s no return statement after calling _reject. Wouldn’t it make the then block execute after 1 second? No. The state of a promise object can be changed only once, which means a promise can succeed/fail only once.

Chaining:
As shown above, .then always returns a new Promise, letting us chain Promises, which makes it easier to perform a series of asynchronous operations as if they are synchronous.

wait(1000).then(function(_result) {
console.log(_result);
return wait(2000);
})
.then(function(_result) {
console.log(_result);
return wait(3000);
})
.then(function(_result) {
console.log(_result);
return wait(4000);
})
.then(function(_result) {
console.log(_result);
return wait(5000);
})
.then(function(_result) {
console.log(_result);
return wait(6000);
})
.then(function(_result) {
console.log(_result);
return wait(7000);
})
.catch(function(_error) {
console.log(_error);
});

This way, we can chain all the promises together. Imagine implementing the same code without using Promise. This would be a callback hell. The output of this example would be:

Resolved in 1 second(s).
Resolved in 2 second(s).
Resolved in 3 second(s).
Resolved in 4 second(s).
Rejected wait time 5 seconds.

As seen in this output, the promise chain will be broken when a promise is rejected. In this case, it jumps over to the catch block. We can further extend the promise chain even after the catch block, and catch doesn’t necessarily have to be the last block in the chain. A promise chain can have more than one catch block. When a promise is resolved, it will look for the next then block in the chain. And in the same way, when a promise is rejected, it will look for the next catch block in the chain and it will continue in both cases.

.then in fact takes two functions as arguments where the first one will be called in case the promise is resolved and the second will be called when a promise is rejected, as below.

promise.then(function() {
// Called when promise is resolved
}, function() {
// Called when promise is rejected
});

.catch is nothing but a short form of:

promise.then(null, function() {
// called when promise is rejected
});

Promise.all
When you want to execute a bunch of asynchronous operations together, you can use Promise.all. This takes an array of promise objects as argument and will be resolved when all the promises in the array are resolved. If any of the promises in the array is rejected, it will be rejected without even waiting for the status of the rest of the promises in the array.

var promises = [];

promises.push(wait(1000));
promises.push(wait(2000));
promises.push(wait(3000));
promises.push(wait(4000));

Promise.all(promises)
.then(function(_results) {
// All the promises in `promises` array are resolved.
});

In the above example, _results contains an array of results of all promises in the same order in which they are added to promises array. Hence the result of the above operation would be:

Resolved in 1 second(s).
Resolved in 2 second(s).
Resolved in 3 second(s).
Resolved in 4 second(s).

Organizations building mobile apps with cross platform tools like Axway Titanium need to be sure to use the current ES6 standards and maintain the code in such a way that it is ready to be updated to the latest iOS and/or Android OS versions. Promises will indeed help you and your team keep your code clean and maintainable. But if your organization needs more help creating clean and maintainable code, please don’t hesitate to reach out. We’d love to get you started.

Eswar Jayavarapu

I'm a Senior Mobile Application developer with over 7 years of experience in developing enterprise mobile applications for various platforms like iOS, Android and Windows. I always like to evaluate and learn new technologies that can help building better solutions. I started off as a backend web-services developer and later with the interest in building mobile applications, started building them which I enjoy doing now. I like the journey of bringing ideas to life with the help of technology.

More Posts

Follow Me:
LinkedIn