Skip to content

Instantly share code, notes, and snippets.

@tylerodonnell
Forked from odigity/Bluebird.txt
Created September 21, 2018 14:21
Show Gist options
  • Save tylerodonnell/bd44a0437a3f0608f442a6087313769c to your computer and use it in GitHub Desktop.
Save tylerodonnell/bd44a0437a3f0608f442a6087313769c to your computer and use it in GitHub Desktop.
A Snapshot of my Bluebird.js Cheat Sheet.
┌──────────┐
──┤ Overview ├─────────────────────────────────────────────────────────────────
└──────────┘
$ npm install --save bluebird
const Promise = require('bluebird')
const loaded = new Promise( (resolve, reject) => {
window.addEventListener( 'load', resolve )
})
loaded.then( () => {
// window is loaded here
})
── Using in Libraries ──
`.asCallback()` can be used to create APIs that both accept node-style callbacks and return promises.
┌────────┐
──┤ Config ├───────────────────────────────────────────────────────────────────
└────────┘
Promise.config({ ... })
longStackTraces: true | false (default)
warnings: true | false (default) // Run node with `--trace-warnings` to see full stack traces for warnings.
warnings.wForgottenReturn: true | false (default)
cancellation: true | false (default)
monitoring: true | false (default)
Defaults can be changed by Env Vars.
── Environment Variables ──
Only applies to Node.js or io.js.
BLUEBIRD_DEBUG — Will enable long stack traces and warnings.
BLUEBIRD_WARNINGS — Will enable warnings.
BLUEBIRD_LONG_STACK_TRACES — Will enable long stack traces.
BLUEBIRD_W_FORGOTTEN_RETURN — Will enable 'wForgottonReturn warnings.
NODE_ENV — Same as BLUEBIRD_DEBUG if set exactly to 'development'.
┌───────────────┐
──┤ Class Methods ├────────────────────────────────────────────────────────────
└───────────────┘
None of the collection methods modify the original input.
Holes in arrays are treated as if they were defined with the value undefined.
── new Promise( (resolve, reject) => {} ) -> Promise
── Promise.all( Iterable | Promise<Iterable> ) -> Promise<Array>
Returns a promise that is fulfilled when all the items in the array are fulfilled.
The promise's fulfillment value is an array with fulfillment values at respective positions to the original array.
If any promise in the array rejects, the returned promise is rejected with the rejection reason.
── Promise.any( Iterable | Promise<Iterable> ) -> Promise
Like `Promise.some()`, with 1 as count. If the promise fulfills, the fulfillment value is the value directly rather than an array of 1.
── Promise.bind( any | Promise thisArg, [any | Promise value] ) -> BoundPromise
A bound promise will call its handlers with the bound value set to `thisArg`.
Additionally, promises derived from a bound promise will also be bound promises with the same thisArg binding as the original promise.
Note that bind is only propagated with promise transformation.
If you create new promise chains inside a handler, those chains are not bound to the "upper" thisArg.
`.bind({})` -> Good way to create a shared store accessible by the rest of the chain.
If you don't want to return a bound promise to the consumers of a promise, you can rebind the chain at the end: `.bind()`
── Promise.config() // See Config.
── Promise.delay( ms ) -> Promise
── Promise.each( Iterable | Promise<Iterable>, (item, index, length) => { iterator } ) -> Promise
Iteration happens serially.
If the iterator function returns a promise or a thenable, then the result of the promise is awaited before continuing with next iteration.
If any promise in the input array is rejected, then the returned promise is rejected as well.
Resolves to the original array unmodified. This method is meant to be used for side effects.
── Promise.filter( Iterable | Promise<Iterable>, (item, index, length) => { filterer }, [{ concurrency }] ) -> Promise
Essentially an efficient shortcut for `Promise.map()` + Array#filter.
── Promise.getNewLibraryCopy() -> Object
Returns a new independent copy of the Bluebird library.
This method should be used before you use any of the methods which would otherwise alter the global Bluebird object - to avoid polluting global state.
── Promise.join( Promise, ..., (result, ...) => { handler } ) -> Promise
The result values of all fufilled promises, in order provided.
While `.all()` is good for handling a dynamically sized list of uniform promises,
`Promise.join` is much easier (and more performant) to use when you have a fixed amount of promises.
── Promise.map( Iterable | Promise<Iterable>, (item, index, length) => { mapper }[, { concurrency }] ) -> Promise
If any promise in the array is rejected, or any promise returned by the mapper function is rejected, the returned promise is rejected as well.
The mapper function for a given item is called as soon as possible, i.e., when the promise for that item's index in the input array is fulfilled.
This doesn't mean that the result array has items in random order, it means that `.map()` can be used for concurrency coordination - unlike `.all()`.
── Promise.mapSeries( Iterable | Promise<Iterable>, (item, index, length) => { mapper } ) -> Promise
Like `Promise.map()`, but processes items in order serially, rather than concurrently.
── Promise.method( (...args) => { fn } ) -> function
The new function will always return a promise that is fulfilled with the original functions return values
or rejected with thrown exceptions from the original function.
── Promise.onPossiblyUnhandledRejection( (error, Promise) => { handler } ) -> undefined
Add handler as the handler to call when there is a possibly unhandled rejection.
The default handler logs the error stack to `stderr` or `console.error` in browsers.
Passing no value or a non-function will have the effect of removing any kind of handling for possibly unhandled rejections.
Specific to the bluebird instance its called on. Application developers should use global rejection events
── Promise.promisify() // See Promisification.
── Promise.promisifyAll() // See Promisification.
── Promise.props( Object | Map | Promise<Object|Map> ) -> Promise
Like `Promise.all()`, but with objects instead of arrays. (Waits on object's property values to resolve.)
── Promise.race( Iterable | Promise<Iterable> ) -> Promise
Return a promise that is fulfilled or rejected as soon as a promise in the array is fulfilled or rejected with the respective rejection reason or fulfillment value.
Bluebird provides `Promise.race()` with ES6 semantics, but recommends `Promise.any()` which does what is usually mistakenly expected from `Promise.race()`.
── Promise.reduce( Iterable | Promise<Iterable>, (accumulator, item, index, length) => { reducer }, [initialValue] ) -> Promise
If any promise in the array is rejected or a promise returned by the reducer function is rejected, the result is rejected as well.
If initialValue is undefined (or a promise that resolves to undefined) and the iterable contains only 1 item,
the callback will not be called and the iterable's single item is returned.
If the iterable is empty, the callback will not be called and initialValue is returned (which may be undefined).
`Promise.reduce()` will start calling the reducer as soon as possible, this is why you might want to use it over `Promise.all()`.
── Promise.reject(error) -> Promise
Create a promise that is rejected with the given error.
── Promise.resolve( value ) -> Promise
Create a promise that is resolved with the given value.
If value is already a trusted Promise, it is returned as is.
If value is a thenable (Promise-like object, like those returned by jQuery's $.ajax), returns a trusted Promise that assimilates the state of the thenable.
If value is not a thenable, a fulfilled Promise is returned with value as its fulfillment value.
── Promise.some( Iterable | Promise<Iterable>, count ) -> Promise
Return a promise that is fulfilled as soon as `count` promises are fulfilled.
The fulfillment value is an array with count values in the order they were fulfilled.
If too many promises are rejected so that the promise can never become fulfilled,
it will be immediately rejected with an `AggregateError` of the rejection reasons in the order they were thrown.
── Promise.try( () => { fn } ) -> Promise
Start chain of promises. Synchronous exceptions will be turned into rejections on the returned promise.
── Promise.using() // See Resource Management.
┌────────────────┐
──┤ Object Methods ├───────────────────────────────────────────────────────────
└────────────────┘
── p.all() // Same as `Promise.all(this)`.
── p.any() // Same as `Promise.any(this)`.
── p.bind() // Same as `Promise.bind(this)`.
── p.call( methodName, [args...] ) // -equiv to- `.then( (obj) => { return obj[methodName].call( obj, arg... ) } )`
── p.catchReturn( [ErrorClass | (error) => { predicate },] value ) -> Promise // -equiv to- `.catch( () => { return value } )`
── p.catchThrow( [ErrorClass | (error) => { predicate },] reason ) -> Promise // -equiv to- `.catch( () => { throw reason } )`
── p.cancel() // See Cancellation.
── p.catch( (error) => { handler } ) -> Promise // Catch-All: Shortcut for calling `.then(null, handler)`.
── p.catch( ErrorClass | (error) => { predicate }, (error) => { handler } ) -> Promise // Filtered Catch
For a parameter to be an error type filter, the constructor must have its `.prototype` be `instanceof Error`.
`function MyCustomError() {}; MyCustomError.prototype = Object.create(Error.prototype)`
If you pass a predicate function, the return result will be determine whether the error handler should be called.
By not returning a rejected value or throwing from a catch, you "recover from failure" and continue the chain.
── p.delay() // Same as `Promise.delay(this)`.
── p.each() // Same as `Promise.each(this)`.
── p.error( [(error) => { rejectedHandler }] ) -> Promise
Only catches `OperationalError`. (Results from proper promise rejection, not thrown errors.)
── p.filter() // Same as `Promise.filter(this)`.
── p.finally( () => { handler } ) -> Promise
Unless it throws an exception, the function has no effect on the fulfilled or rejected value of the returned promise.
── p.get( propertyName | index ) -> Promise // -equiv to- `.then( (obj) => { return obj[propertyName] } )`
── p.isCancelled() -> boolean
── p.isFulfilled() -> boolean
── p.isPending() -> boolean
── p.isRejected() -> boolean
── p.map() // Same as `Promise.map(this)`.
── p.mapSeries() // Same as `Promise.mapSeries(this)`.
── p.props() // Same as `Promise.props(this)`.
── p.reason() -> rejection_reason // Throws error if promise isn't rejected.
── p.reduce() // Same as `Promise.reduce(this)`.
── p.return(value) -> Promise // -equiv to- `.then( () => { return value } )`
── p.some() // Same as `Promise.some(this)`.
── p.spread( [(values...) => { fulfilledHandler }] ) -> Promise
Like `.then()`, but value must be an array, which is flattened. Implicitly adds `.all()`.
── p.tap( (value) => { handler } ) -> Promise
Let's you access the fulfilled value while not interupting the chain. (The same value is passed to the next link.)
If you return a promise, it's waited on.
Unlike `.finally()` this is not called for rejections.
── p.tapCatch( [ErrorClass | (error) => { predicate },] (value) => { handler } ) -> Promise
A convenience method for accessing errors without handling them.
Similar to `.finally()`, but only called on rejections.
── p.then( [(value) => { fulfilledHandler }], [(error) => { rejectedHandler }] ) -> Promise
── p.throw(reason) -> Promise // -equiv to- `.then( () => { throw reason } )`
── p.timeout( ms, [error | message] ) -> Promise
Returns a promise that will be fulfilled with this promise's fulfillment value or rejection reason.
However, if this promise is not fulfilled or rejected within ms milliseconds, the returned promise is rejected with either:
• A `TimeoutError` with specified message or default message.
• The specified error.
── p.value() -> value
┌──────────────┐ Off by default. Enable it using `Promise.config()`.
──┤ Cancellation ├─────────────────────────────────────────────────────────────
└──────────────┘
Cancelling a promise simply means that its handler callbacks will not be called.
As an optimization, the cancellation signal propagates upwards the promise chain so that an ongoing operation e.g. network request can be aborted.
The handlers registered with `.finally()` are still called.
const p = new Promise( (resolve, reject, onCancel) => {
var xhr = new XMLHttpRequest()
...
onCancel( () => { xhr.abort() } )
})
p.cancel()
`.cancel()` is synchronous, while `onCancel()` is called asynchronously.
Note that the `onCancel()` hook is really an optional optimization.
As such, any errors that may occur while inside the onCancel callback are not caught and turned into rejections.
┌──────────────┐
──┤ Promisifying ├─────────────────────────────────────────────────────────────
└──────────────┘
Most libraries can be promisified by requiring the library's classes (constructor functions) and calling `promisifyAll()` on the `.prototype`.
Promise.promisify — Converts a single callback-taking function into a promise-returning function.
Does not alter the original function. Returns modified version.
Promise.promisifyAll — Takes object full of functions and converts them into new ones with the `Async` suffix (by default).
Does not change the original functions, but instead adds new ones.
Any class properties of the object are also promisified, both static and instance methods.
The entire prototype chain of the object is promisified on the object. Only enumerable are considered.
If the object already has a promisified version of the method, it will be skipped.
Uses dynamic recompilation for really fast wrappers and thus calling them should be done only once.
`Promise.fromCallback()` exists for cases where this is not possible.
── Promise.promisify( (arg..., callback) => { nodeFunction }, [{ multiArgs=false, context=this }] ) -> function
Setting `multiArgs` to true means the resulting promise will always fulfill with an array of the callback's success values.
If you pass a context, `nodeFunction` will be called as a method on the context.
Can also just do: `promisified.call( context, args... )`
── Promise.promisifyAll( { target } [, {
suffix: String="Async",
multiArgs: boolean=false,
filter: (String name, function func, Object target, boolean passesDefaultFilter) => {} -> boolean,
promisifier: (function originalFunction, function defaultPromisifier) => {}
}]) -> Object
The default filter function will ignore:
• properties that start with a leading underscore
• properties that are not valid JavaScript identifiers
• constructor functions (function which have enumerable properties in their `.prototype`)
── Promisifying an Object Method ──
const foo = { // create object
state: 42, // give it state
action: function (cb) { // create method that (a) uses the state (b) accepts node-style callback
cb( null, this.state * 2 ) // invoke callback with return value
}
}
foo.action( (error, rval) => { console.log(`rval: ${rval}`) } ) // test normal use of object method
const paction = Promise.promisify( foo.action, { context: foo } ) // promisify `action` method, pass object as bind context
paction() // invoke promisified object method
.then( (rval) => { console.log(`rval: ${rval}`) } )
.catch( (error) => { console.log(`error: ${error}`) } )
┌──────────────────────┐
──┤ Promisify — Examples ├─────────────────────────────────────────────────────
└──────────────────────┘
const fs = Promise.promisifyAll(require('fs'))
const fsextra = Promise.promisifyAll(require('fs-extra'))
const jsdom = Promise.promisifyAll(require('jsdom'))
const mkdirp = Promise.promisifyAll(require('mkdirp')) // Use `mkdirp.mkdirpAsync()`, not `mkdirp()`.
const mongodb = Promise.promisifyAll(require('mongodb'))
const mongoose = Promise.promisifyAll(require('mongoose'))
Promise.promisifyAll(require('mysql/lib/Connection').prototype) // Because mysql's classes are not properties of the main export.
Promise.promisifyAll(require('mysql/lib/Pool').prototype)
const ncp = Promise.promisifyAll(require('ncp'))
const nodemailer = Promise.promisifyAll(require('nodemailer'))
const pg = Promise.promisifyAll(require('pg'))
const prompt = Promise.promisifyAll(require('prompt'))
const redis = Promise.promisifyAll(require('redis'))
const request = Promise.promisifyAll(require('request')) // Use `request.getAsync()`, not `request()`.
const rimrafAsync = Promise.promisify( require('rimraf')) // The module isn't promisified, but the function returned is.
const winston = Promise.promisifyAll(require('winston'))
const xml2js = Promise.promisifyAll(require('xml2js'))
┌─────────────────────┐
──┤ Resource Management ├──────────────────────────────────────────────────────
└─────────────────────┘
Disposers — Objects that wrap a resource and a method to release that resource.
`Promise.using()` — A function to safely use disposers in a way that automatically calls their release method.
── p.disposer( (resource, usingResultPromise ) => { disposalHandler } ) -> Disposer
A meta method used to specify the disposer method that cleans up a resource when using `Promise.using()`.
usingResultPromise — The result promise of the using block, which you can inspect synchronously.
If you anticipate thrown errors or promise rejections while disposing of the resource you should use a `try...catch` block.
── Promise.using( Promise | Disposer, ..., (resources...) => { handler } ) -> Promise
── Promise.using( Array, (Array) => { handler } ) -> Promise
Will make sure that the specified disposer will be called when the promise you return from your '.using()' callback has settled.
The disposer is necessary because there is no standard interface in node for disposing resources.
── Example ──
function getConnection () {
return db.connect().disposer(
(connection, promise) => { connection.close() }
)
}
function useConnection (query) {
return Promise.using( getConnection(), (connection) => {
return connection.sendQuery(query)
})
}
This will ensure that `connection.close()` will be called once the promise returned from the `Promise.using()` closure is resolved
or if an exception was thrown in the closure body.
┌──────────────────────┐
──┤ Built-In Error Types ├─────────────────────────────────────────────────────
└──────────────────────┘
Promise.AggregateError — A collection of errors. An array-like object, with numeric indices and a `.length` property.
It supports all generic array methods such as `.forEach()` directly.
Caught in `.error()` handlers, even if the contained errors are not Operational.
Used by `Promise.some()` and `Promise.any()` when they fail.
Promise.CancellationError — Signals operation has been aborted or cancelled.
Promise.OperationalError — Represents explicit promise rejection as opposed to a thrown error.
If an error is errbacked by a promisified method and is not a typed error,
it will be converted to a OperationalError with the original error in `.cause`.
Caught in `.error()` handlers.
Promise.TimeoutError — Signals operation has timed out.
┌──────────────────────────────────┐
──┤ Debuggability and Error Handling ├─────────────────────────────────────────
└──────────────────────────────────┘
An error is an object that is a `instanceof Error`.
It will at minimum have the properties `.stack` and `.message`,
which are an absolute must have for any value that is being used in an automatic propagation mechanism, such as exceptions and rejections.
Surfacing Unhandled Errors
The default approach of bluebird is to immediately log the stack trace when there is an unhandled rejection.
Long Stack Traces
Bluebird's long stack traces additionally eliminate cycles, don't leak memory,
are not limited to a certain amount of asynchronous boundaries and are fast enough for most applications to be used in production.
When using longStackTraces, call `.config()` immediately after requiring Bluebird.
In order to get full stack traces with warnings in Node 6.x+ you need to enable to `--trace-warnings` flag.
To enable long stack traces and warnings in node development:
$ NODE_ENV=development node server.js
── Global Rejection Events ──
unhandledRejection — Corresponds to the local `Promise.onPossiblyUnhandledRejection()`.
rejectionHandled — Corresponds to the local `Promise.onUnhandledRejectionHandled()`.
process.on( <event>, (reason, promise) => {} )
window.addEventListener( <event>, (e) => {
e.preventDefault() // Must be called to prevent the default action which is currently to log the stack trace to `console.warn`.
const reason = e.detail.reason
const promise = e.detail.promise
})
┌──────────┐
──┤ Read Log ├─────────────────────────────────────────────────────────────────
└──────────┘
☑ http://bluebirdjs.com/docs/anti-patterns.html
☑ http://bluebirdjs.com/docs/api-reference.html
☑ http://bluebirdjs.com/docs/api/aggregateerror.html
☑ http://bluebirdjs.com/docs/api/all.html
☑ http://bluebirdjs.com/docs/api/any.html
☑ http://bluebirdjs.com/docs/api/ascallback.html
☑ http://bluebirdjs.com/docs/api/bind.html
☑ http://bluebirdjs.com/docs/api/built-in-error-types.html
☑ http://bluebirdjs.com/docs/api/call.html
☑ http://bluebirdjs.com/docs/api/cancel.html
☑ http://bluebirdjs.com/docs/api/cancellationerror.html
☑ http://bluebirdjs.com/docs/api/cancellation.html
☑ http://bluebirdjs.com/docs/api/catch.html
☑ http://bluebirdjs.com/docs/api/catchreturn.html
☑ http://bluebirdjs.com/docs/api/catchthrow.html
☑ http://bluebirdjs.com/docs/api/collections.html
☑ http://bluebirdjs.com/docs/api/core.html
☑ http://bluebirdjs.com/docs/api/deferred-migration.html
☑ http://bluebirdjs.com/docs/api/delay.html
☑ http://bluebirdjs.com/docs/api/disposer.html
☑ http://bluebirdjs.com/docs/api/done.html
☑ http://bluebirdjs.com/docs/api/each.html
☑ http://bluebirdjs.com/docs/api/environment-variables.html
☑ http://bluebirdjs.com/docs/api/error.html
☑ http://bluebirdjs.com/docs/api/error-management-configuration.html
☑ http://bluebirdjs.com/docs/api/filter.html
☑ http://bluebirdjs.com/docs/api/finally.html
☑ http://bluebirdjs.com/docs/api/generators.html
☑ http://bluebirdjs.com/docs/api/get.html
☑ http://bluebirdjs.com/docs/api/iscancelled.html
☑ http://bluebirdjs.com/docs/api/isfulfilled.html
☑ http://bluebirdjs.com/docs/api/ispending.html
☑ http://bluebirdjs.com/docs/api/isrejected.html
☑ http://bluebirdjs.com/docs/api/map.html
☑ http://bluebirdjs.com/docs/api/mapseries.html
☑ http://bluebirdjs.com/docs/api/new-promise.html
☑ http://bluebirdjs.com/docs/api/operationalerror.html
☑ http://bluebirdjs.com/docs/api/progression-migration.html
☑ http://bluebirdjs.com/docs/api/promise.all.html
☑ http://bluebirdjs.com/docs/api/promise.any.html
☑ http://bluebirdjs.com/docs/api/promise.bind.html
☑ http://bluebirdjs.com/docs/api/promise.config.html
☑ http://bluebirdjs.com/docs/api/promise.coroutine.addyieldhandler.html
☑ http://bluebirdjs.com/docs/api/promise.coroutine.html
☑ http://bluebirdjs.com/docs/api/promise.each.html
☑ http://bluebirdjs.com/docs/api/promise.filter.html
☑ http://bluebirdjs.com/docs/api/promise.fromcallback.html
☑ http://bluebirdjs.com/docs/api/promise.getnewlibrarycopy.html
☑ http://bluebirdjs.com/docs/api/promiseinspection.html
☑ http://bluebirdjs.com/docs/api/promise.join.html
☑ http://bluebirdjs.com/docs/api/promise.map.html
☑ http://bluebirdjs.com/docs/api/promise.mapseries.html
☑ http://bluebirdjs.com/docs/api/promise.method.html
☑ http://bluebirdjs.com/docs/api/promise.noconflict.html
☑ http://bluebirdjs.com/docs/api/promise.onpossiblyunhandledrejection.html
☑ http://bluebirdjs.com/docs/api/promise.promisifyall.html
☑ http://bluebirdjs.com/docs/api/promise.promisify.html
☑ http://bluebirdjs.com/docs/api/promise.props.html
☑ http://bluebirdjs.com/docs/api/promise.race.html
☑ http://bluebirdjs.com/docs/api/promise.reduce.html
☑ http://bluebirdjs.com/docs/api/promise.reject.html
☑ http://bluebirdjs.com/docs/api/promise.resolve.html
☑ http://bluebirdjs.com/docs/api/promise.setscheduler.html
☑ http://bluebirdjs.com/docs/api/promise.some.html
☑ http://bluebirdjs.com/docs/api/promise.try.html
☑ http://bluebirdjs.com/docs/api/promise.using.html
☑ http://bluebirdjs.com/docs/api/promisification.html
☑ http://bluebirdjs.com/docs/api/props.html
☑ http://bluebirdjs.com/docs/api/reason.html
☑ http://bluebirdjs.com/docs/api/reduce.html
☑ http://bluebirdjs.com/docs/api/reflect.html
☑ http://bluebirdjs.com/docs/api/resource-management.html
☑ http://bluebirdjs.com/docs/api/return.html
☑ http://bluebirdjs.com/docs/api/some.html
☑ http://bluebirdjs.com/docs/api/spread.html
☑ http://bluebirdjs.com/docs/api/suppressunhandledrejections.html
☑ http://bluebirdjs.com/docs/api/synchronous-inspection.html
☑ http://bluebirdjs.com/docs/api/tapcatch.html
☑ http://bluebirdjs.com/docs/api/tap.html
☑ http://bluebirdjs.com/docs/api/then.html
☑ http://bluebirdjs.com/docs/api/throw.html
☑ http://bluebirdjs.com/docs/api/timeouterror.html
☑ http://bluebirdjs.com/docs/api/timeout.html
☑ http://bluebirdjs.com/docs/api/timers.html
☑ http://bluebirdjs.com/docs/api/utility.html
☑ http://bluebirdjs.com/docs/api/value.html
☑ http://bluebirdjs.com/docs/async-dialogs.html
☑ http://bluebirdjs.com/docs/beginners-guide.html (INCOMPLETE)
☑ http://bluebirdjs.com/docs/benchmarks.html
☑ http://bluebirdjs.com/docs/changelog.html
☑ http://bluebirdjs.com/docs/coming-from-other-languages.html
☑ http://bluebirdjs.com/docs/coming-from-other-libraries.html
☑ http://bluebirdjs.com/docs/contribute.html
☑ http://bluebirdjs.com/docs/deprecated-apis.html
☑ http://bluebirdjs.com/docs/download-api-reference.html
☑ http://bluebirdjs.com/docs/error-explanations.html
☑ http://bluebirdjs.com/docs/features.html
☑ http://bluebirdjs.com/docs/getting-started.html
☑ http://bluebirdjs.com/docs/install.html
☑ http://bluebirdjs.com/docs/new-in-bluebird-3.html
☑ http://bluebirdjs.com/docs/support.html
☑ http://bluebirdjs.com/docs/warning-explanations.html
☑ http://bluebirdjs.com/docs/what-about-generators.html
☑ http://bluebirdjs.com/docs/why-bluebird.html
☑ http://bluebirdjs.com/docs/why-performance.html (INCOMPLETE)
☑ http://bluebirdjs.com/docs/why-promises.html
☑ http://bluebirdjs.com/docs/working-with-callbacks.html
☑ https://github.com/petkaantonov/bluebird/
☑ https://github.com/petkaantonov/bluebird/wiki/
☐ https://www.promisejs.org/
☐ https://www.promisejs.org/api/
☐ https://www.promisejs.org/generators/
☐ https://www.promisejs.org/implementing/
☐ https://www.promisejs.org/patterns/
☐ https://www.youtube.com/watch?v=qbKWsbJ76-s Forbes Lindesay: Promises and Generators: control flow utopia -- JSConf EU 2013
☐ https://promisesaplus.com/
☑ http://stackoverflow.com/questions/34960886/are-there-still-reasons-to-use-promise-libraries-like-q-or-bluebird-now-that-we
☐ http://davidvgalbraith.com/how-does-bluebird-promisify-work/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment