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!