NodeSchool Cleveland

October 19, 2015

Promise It Won't Hurt

Thanks to our sponsors

Tonight's workshopper...

Promise It Won't Hurt

Promises?

Why Node.js?
Efficient
Programs
←
Programming
Environment
→
Developer
Productivity

Node's Approach

Target the slowest, most difficult parts of a program
Access TypeCycles
L1 Cache3
L2 Cache14
RAM250
Disk41 000 000
Network240 000 000

Possible Solutions

Synchronous programming
Create processes
Create threads
Event-Driven, non-blocking architecture

Cut to the Chase

1 thread for your code.
Node will perform the costly I/O operations using a thread pool.

Recap

  1. Your code will never be interrupted.
  2. I/O will not block

Source: http://blog.mixu.net/2011/02/01/understanding-the-node-js-event-loop/

So what does this look like?

Typical Callback Usage


var fs = require('fs');

fs.readFile(
    'file1.txt',
    function (err, data) {
        if (err) {throw err;}
        console.log(data);
    }
);
                    

Mulitple Async Operations - Sequential


var fs = require('fs');

fs.readFile(
    'file1.txt',
    function (err, data) {
        if (err) {throw err;}

        fs.readFile(
            'file2.txt',
            function (err, data) {
                if (err) {throw err;}
                console.log(data);
            }
        );
    }
);
                    

Multiple Async Operations - Concurrently


var fs = require('fs'),
    numCompleted = 0,
    onFileRead = function (err, data) {
        if (err) {throw err;}

        numCompleted += 1;
        if (numCompleted === 2) {
            // Both async operation have been completed
        }
    };

fs.readFile('file1.txt', onFileRead);
fs.readFile('file2.txt', onFileRead);
                    

Promises

A placeholder for a value that may be available in the future.

It will be fulfilled or rejected... once!

Using a promise


var file1Promise = readFilePromise('file1.txt');
file1Promise.then(
    function onFulfilled(data) {console.log(data);},
    function onRejected(err) {throw err;}
);
                    

var promise1 = readFilePromise('file1.txt');
var wat = promise1.then(
    function onFulfilled(data) { /* ... */ },
    function onRejected(err) { /* ... */ }
);
                    

Q: What does then() return?
(What is wat?)


var promise1 = readFilePromise('file1.txt');
var promise2 = promise1.then(
    function onFulfilled(data) { /* ... */ },
    function onRejected(err) { /* ... */ }
);
                    

Q: What does then() return?

A: A promise


var promise1 = readFilePromise('file1.txt');
var promise2 = promise1.then(
    function onFulfilled(data) { /* ... */ },
    function onRejected(err) { /* ... */ }
);
                    

1 of 3 things can happen in your handlers:

  1. Return a value
    then() will return a promise that has been fulfilled with that value.
  2. Throw an exception
    then() will return a promise that has been rejected with that exception.
  3. Return a promise
    then() will return that promise.

Reading 2 files sequentially


readFilePromise('file1.txt').then(
    function onFulfilled(data) {
        console.log(data);
        return readFilePromise('file2.txt');
    }
).then(
    function onFulfilled(data) {console.log(data);}
).catch(
    function onRejected(err) {throw err;}
);
                

Reading 2 files concurrently


var q = require('q'),
    aggregatePromise,
    thePromises = [readFilePromise('file1.txt'), readFilePromise('file2.txt')];

aggregatePromise = q.all(thePromises);
aggregatePromise.then(
    function (values) {
        // values[0] is file1.txt data
        // values[1] is file2.txt data
    }
).catch(function onRejected(err) {throw err;});
                    

Converting Callbacks to Promises

(The old way)


var fs = require('fs'),
    q  = require('q');

function promiseReadFile(fileName) {
    var dfd = q.defer();

    fs.readFile(fileName, function (err, data) {
        if (err) { return dfd.reject(err); }

        dfd.resolve(data);
    });

    return dfd.promise;
}
                

Converting Callbacks to Promises

(The new way)


function promiseReadFile(fileName) {
    var promise = new Promise(
        function (resolve, reject) {
            fs.readFile(
                'myfile.txt',
                function (err, data) {
                    if (err) {
                        return reject(err);
                    }
                    resolve(data);
                }
            );
        }
    );
    return promise;
}
                

We're Just Scratching the Surface

  • promise.spread()
  • promise.allSettled()
  • promise.any()
  • promise.race()
  • promise.finally()
  • etc. etc. etc.

Let's get started

To get setup:


$ mkdir promise-it-wont-hurt && cd promise-it-wont-hurt
$ npm install q
$ npm install -g promise-it-wont-hurt@latest
                    

To run:


$ promise-it-wont-hurt
$ promise-it-wont-hurt run program.js
$ promise-it-wont-hurt verfiy program.js
                

This presentation:
http://bit.ly/nsclepresentations

References

Thank You!

Please fill out the survey to help us make NodeSchool CLE even better!