Promises

The first thing to know about promises is that they are an abstraction for asynchronous programming.

Promises are a very important pattern when developing in node.JS and have vast usage.

Promises provide a alternative way for writing asynchronous code with raw callbacks.

Promise are an abstraction and a pattern to solve calling asynchronous code in a more controllable manner.

Promises provide us with a cleaner and more robust way of handling async code.
It also reverts the IOC pattern and returns the control to the caller itself.
So this pattern behavior of promises help us to manage the async code as if it was sync code.

This chapter is an introduction to ECMAScript 6 Promise API in particular.

The default pattern of promise is:

```function readFileAsync() {

return new Promise(
    function (resolve, reject) {

        //...implemention goes here
        resolve(value); // resolving the promise   
        reject(error); // rejecting the promise
    });

The above function can be used as follows:

readFileAsync()
.then(value => { / success / })
.catch(error => { / failure / });

Promises have different states:

  1. Pending - The initial state of a promise.
  2. Fulfilled - The state of a promise representing a successful operation.
  3. Rejected - The state of a promise representing a failed operation.

Promises have a then method, which you can use to get the eventual return value (fulfillment) or thrown exception (rejection).

There are couble of 3rd party libaraies module that are vastly used in the community:

Bluebird:

Bluebird provides promisification on steroids.
Installation goes like:
npm install bluebird

When creating a promise:

new Promise(function (ok, err) { doSomething(function () { if (success) { ok(); } else { err(); } }); })

From consumer prespective

promise
  .then(okFn, errFn)
  .catch(errFn)```

When dealing with an array of promises:

var promises = [
promiseDoSomething(), promiseDoOther(), ...
]

// succeeds when all the above promises succeed
Promise.all(promises)
.then(function (results) {
});

// succeeds when one of the promises finishes first
Promise.race(promises)
.then(function (result) {
});```

You can create from an object api a promisification of all its exposed library methods. For example:
So Now you can use the fs module as if it was designed to use by bluebird promises from the beginning =>

var fs = require("fs");
Promise.promisifyAll(fs);

fs.readFileAsync("file.js", "utf8").then(...)```


Once you've done the above code you just need to add the  "Async"-suffix to method calls and start using the usual promise interface (instead of the callback interface). 

Usually this should be doneon the .prototype (calling the promisifyAll) when requiring the library's classes. 
For example: 

Promise.promisifyAll(require("mysql/lib/Connection").prototype);```

Bluebird promise monitoring:

This is a very nice feature in bluebird which enables us to hook on the lifecycle events of promises in the blubird library:

  • "promiseCreated" - when created through the constructor.
  • "promiseChained" - when created through chaining (e.g. .then).
  • "promiseFulfilled" - when a promise is fulfilled.
  • "promiseRejected" - when a promise is rejected.
  • "promiseResolved" - when a promise adopts another's state.
  • "promiseCancelled" - when a promise is cancelled.

In order to enable this promise you need to manually call Promise.config with monitoring: true.

canceling a promise:

With the bluebird library it is also possible to cancel a library:

var Promise = require('bluebird');

var parentPromise = Promise.resolve(42)
    .then((val1) => {
        console.log(val1);
        return val1 + 1;
    })
    .then((val2) => {
        console.log(val2);
        return val2 + 1;
    })
    .cancellable()//from here  =>now you can cancel the promise
    .then((val3) => {
        const randomValue = parseInt(Math.random() * 10)
        console.log('random value:' + randomValue);
        return randomValue;
    })
    .then((randomValue) => {
        console.log(randomValue);
        if (randomValue <= 5) {
            console.log('cancelling the promise');
            return parentPromise.cancel('value cannot be lower then five');
        }
        console.log('continuing the promise');
        return someRndValue + 1;
    })
    .then((val4) => {
        //this code will not be reached if someRndValue<5
        console.log(val4);
        return val4;
    })
    .catch(Promise.CancellationError, function (err) {
        //this code will be reached only if someone calls without reason : parentPromise.cancel();
        console.log('CancellationError:' + err);
    })
    .catch((err) => {

        console.log(err.message);
    });

Node.js 8:util.promisify()

Node.js 8 has a new utility function:util.promisify().

It converts a callback-based function to a Promise-based one. This contribution is mainly by Benjamin

For example the following code :

If you hand the path of a file to the following script, it prints its contents.

const {promisify} = require('util');

const fs = require('fs');

const readFileAsync = promisify(fs.readFile); // (A)

const filePath = process.argv[2];

readFileAsync(filePath, {encoding: 'utf8'})

.then((text) => {

console.log('CONTENT:', text);

})

.catch((err) => {

console.log('ERROR:', err);

});

The Q library

A tool for creating and composing asynchronous promises in JavaScript
The Q library created by kris kowal and is one of the main libraries.

To promisify a callback with the Q library:

Q.fcall(promisedStep1) .then(promisedStep2) .then(promisedStep3) .then(promisedStep4) .then(function (value4) { // Do something with value4 }) .catch(function (error) { // Handle any error from all above steps }) .done();

An imprtant article on how we are miising the point about promises can be found here.

results matching ""

    No results matching ""