I Promised to to make my API call
What are Promises?
A promise represents the eventual result of an asynchronous operation.
https://github.com/promises-aplus/promises-spec
Wat?
It turns this...
into this
function retweetAllThe(hashtag, cb) {
twitter.hashtagged(hashtag, function(err, allTheThings) {
if (err) { return cb(err); }
else {
twitter.reTweet(allTheThings, function(err, numberOfRetweets) {
if (err) { return cb(err); }
else {
return cb(undefined, numberOfRetweets);
}
});
}
});
};
retweetAllThe('cats', function(err, numberOfRetweets) {
if (err) { console.log('Where have all the cats gone?'); }
else { console.log(numberOfTweets); }
});
twitter.hashtagged(hashtag)
.then(twitter.reTweet)
.then(console.log)
.catch(function(err) {
console.log('Where have all the cats gone?');
});
Promises releases you from the shackles of callback hell.
By wrapping each function into something that returns a then.
*But you should really understand Callbacks first. Knowing how to write a piece of code as a callback means that it'll work as a promise as well.
A Then, or thennable, as some people call it, is any resulting object that has a .then property.
The .then property allows other promises/functions to chain off the original promise by inserting another function as the parameter to the .then().
Hokay, So.
How do I start a Promise?
Well, you probably won't be starting any promises... probably.
Most libraries are starting to support Promises or can be modified to support them.
Okay, I lied.
Sometimes you need to start your own Promise.
To start a promise...
Text
function someFunction(params) {
return new Promise(function(resolve, reject) {
// do something with params
// end with calling resolve(whatYouWantToReturn);
// or with reject(err);
});
}
someFunction('something')
.then(function(result) {
// do something with the results
})
.catch(function(err) {
// all your errors are belong to this function
});
What if I want to do thing concurrently?
function spark(power) {
return new Promise(function(resolve, reject) {
power.connect();
return resolve('sparked');
});
}
function pump(fuel) {
return new Promise(function(resolve, reject) {
fuel.flow();
return resolve('pumping');
});
}
var fuelPump = pump(gas);
var starter = spark(electricity);
return Promise.join(starter, fuelPump)
.then(function(actions) {
// ['sparked', 'pumping']
if (actions.length === 2) { console.log('Engine started'); }
});
.catch(function(err) {
console.log('boom.');
});
So why should I use Promises?
It's the future of JavaScript.
ES6 will come with Promises natively.
Because callbacks kinda do suck.
Also, it's fast.
It's about 14% slower compared to native unflattened callbacks but that shouldn't matter unless you do about 10000 ops/sec @ 1ms per I/O op.
For comparison, async-waterfall is about 300% slower.
http://spion.github.io/posts/why-i-am-switching-to-promises.html
The real reason to use promises...
Text
// Positive case only
someFunction('something')
.then(function(result) {
// do something with the results\
throw new Error('OH NOEESSSS!');
})
.catch(function(err) {
// all your errors are belong to this function
console.log(err); // OH YES!
});
// Callback form (must always all cases)
someFunction(param, cb) { // cb = anotherFunction
// need to ensure param is valid
return cb(err, result); // need to pass errors down the road here
}
anotherFunction(err, value, cb) {
// need to handle err here or pass it on
// do something with value
// pass error or generate a new on
return cb(err, value);
}
So I can't use it now?
Promise Libraries
https://github.com/kriskowal/q
https://github.com/petkaantonov/bluebird
https://github.com/tildeio/rsvp.js
https://github.com/cujojs/when
https://promisesaplus.com/implementations
OR
https://6to5.org/
https://github.com/google/traceur-compiler
What if I already have callbacks?
Return a Promise from a native callback
function returnPromise(input)
return new Promise(function(resolve, reject) {
someFunction(input, function(err, result) {
if (err) { return reject(err); }
else { return resolve(result); }
});
});
}
The other way around
Have a promise call a callback
function returnCallback(input, cb) {
someFunction(input)
.then(function(result) {
cb(undefined, result);
})
.catch(function(err) {
cb(err);
});
}
Party Tricks
function multiHeadedPromise(medusa, hydra) {
var promiseHolder;
if (medusa) {
promiseHolder = medusa.stare();
}
else {
promiseHolder = hydra.swallow();
}
promiseHolder
.then(function(monster) {
return kill-9(monster);
})
.catch(function(err) {
console.log('i die.');
});
}
Party Tricks
function PromiseMap(finalFantasySummons) {
return Promise.map(finalFantasySummons, function(summon) {
return summon.name;
})
.then(function(summonNames) {
return console.log(summonNames);
// ['bahamut', 'tiamat', 'shiva', 'ifrit']
})
.then(function(summonNames) {
return Promise.each(summonNames, function(name) {
return summon(name);
});
})
.catch(function(err) {
console.log('summons failed.');
});
}
Party Tricks
function AdvancedErros(badInput) {
return new Promise(function(resolve, reject) {
var valid = testInput(badInput);
if (valid) { return resolve(badInput); }
else { throw new Promise.OperationalError('Input is naughty'); }
})
.then(function(validInput) {
// do something with input
})
.then(function(result) {
var validResult = testResult(result);
if (valid) { return result; }
else { throw new Error('This shouldn't happen'); }
})
.error(function(err) {
console.log('Input was naughty');
})
.catch(function(err) {
console.log('Something that shouldn't happen, happened.');
});
.then(function() {
return 'something anyway';
});
}
Behind the Scenes
I've been leading you on
SomePromise()
// .then(function(resolve), function(reject), function(notify))
.then(function(){});
// --> .then(function(){}, null, null);
.catch(function(err) {});
//--> .then(null, function(err) {}, null);
SomePromise()
.then(console.log)
.catch(console.err)
.then(wat);
Behind the Scenes
I've been leading you on
var Promise = require('bluebird');
var db = require('pg');
{
method: 'POST',
path: '/test',
config: {
validate: { payload: { user: Joi.object().required() } },
handler: function(request, reply) {
var user = request.payload.user;
var promise = stupidFunction()
.then(function(user) {
return db.getUser(user); // returns user successfully
})
.catch(BadInputError, function(err) { return Boom.badRequest('Bad Input'); })
.catch(function(err) { return Boom.notFound('Stupid Function'); });
return reply(promise);
}
}
}
RX JS Promises Observables 2.x Node
By tkssharma
RX JS Promises Observables 2.x Node
JavaScript Promises Presentation for HiCapacity
- 934