================================================
FILE: docs/_plugins/mdate.rb
================================================
module Jekyll
module MyFilters
def file_date(input)
File.mtime(input)
end
def check_active(page_path, link_type)
if (link_type == "support" and page_path =~ /support/) or
(link_type == "install" and page_path =~ /install/) or
(link_type == "docs")
"active"
else
""
end
end
end
end
Liquid::Template.register_filter(Jekyll::MyFilters)
================================================
FILE: docs/_plugins/plugin.rb
================================================
require "redcarpet"
require "pygments"
require_relative "../helpers"
class Redcarpet::Render::HTML
def header(title, level)
anchor = Helpers.clean(title)
return <<-eos
#{title}
eos
end
# Hacks to get markdown working inside html blocks ....
def block_html(html)
html.gsub(/([\d\D]+?)<\/markdown>/) {|_|
extensions = {fenced_code_blocks: true}
renderer = Redcarpet::Markdown.new(WithHighlights, extensions)
renderer.render(Regexp.last_match[1])
}
end
def link(link, title, content)
if link == "unfinished-article"
return <<-eos
This article is partially or completely unfinished.
You are welcome to create pull requests
to help completing this article.
eos
elsif link == "."
if content =~ /#\d+/
url = "https://github.com/petkaantonov/bluebird/issues/" + content[1..-1]
else
url = "/docs/api/" + Helpers.clean(content) + ".html"
end
return "#{content}"
else
return "#{content}"
end
end
end
class WithHighlights < Redcarpet::Render::HTML
def block_code(code, language)
Pygments.highlight(code, :lexer => language)
end
end
================================================
FILE: docs/css/main.css
================================================
body {
font-size: 16px;
}
body > .container {
padding-bottom: 50px;
}
.navbar-bluebird {
font-family: 'Raleway', sans-serif;
font-size: 18px;
margin-top: 50px;
text-transform:uppercase;
}
.nav {
font-family: 'Raleway', sans-serif;
}
.nav.bb-nav > li > a{
transition: all 0.3s ease-in-out;
border-bottom: 1px solid rgba(0,0,0,0);
}
.nav.bb-nav > li > a:focus, .nav.bb-nav > li > a:hover,
.nav.bb-nav > li.active > a {
background-color:initial;
border-bottom:1px solid #BE7306;
}
.nav a {
color: #BE7306;
}
.nav.left-nav li a {
padding: 2px 0px;
font-size: 14px;
font-family: 'Raleway', sans-serif;
}
.nav.left-nav li a:focus, .nav.left-nav li a:hover {
background: none;
text-decoration: underline;
}
.navbar-bluebird li {
text-align:center;
}
h1,h2,h3,h4,h5,h6{
font-family: 'Raleway', sans-serif;
/*color:#5275B4;*/
color: #1B4288;
}
.api-code-section h2, code, pre {
font-family: 'Consolas', 'Lucida Console', 'Courier New', 'monospace'
}
body {
margin-top:10px;
}
.icon-bar {
background-color:#5275B4;
}
.promises-showroom .arrow {
text-align: center;
margin-top: 100px;
color:#EC9313;
}
pre{
background-color: initial;
border: none;
margin:0px;
padding:0px;
}
.promises-showroom .hljs{
border-radius: 6px;
padding-left: 30px;
padding-bottom: 15px;
}
.take-action{
position:relative;
min-height:300px;
}
.take-action .cloud-bg{
width: 100%;
height: 300px;
border: none;
}
.take-action .action-buttons{
position:absolute;
top:50%;
text-align:center;
width:100%;
}
.btn-bb {
font-family: 'Raleway', sans-serif;
color: white;
}
.btn-beak{
background-color: #EC9313;
border-bottom: 4px solid #BE7306;
}
.btn-wings {
background-color: #265584;
border-bottom: 4px solid #1A3A59;
}
.btn-bb:hover{
color:white;
}
.undo-margin{
margin-left:-15px;
}
.main-line{
font-family: 'Raleway', sans-serif;
margin-bottom: 59px;
margin-top: -74px;
font-size: 20px;
color:white;
}
.tagline {
font-family: 'Raleway', sans-serif;
font-size:26px;
color:#5275B4;
font-weight:200;
}
.nav-child {
margin-left:20px;
}
.title:hover{
text-decoration:none;
}
.header-anchor {
opacity: 0;
-webkit-transition: opacity 0.2s ease-in-out 0.1s;
-moz-transition: opacity 0.2s ease-in-out 0.1s;
-ms-transition: opacity 0.2s ease-in-out 0.1s;
outline: none;
}
.header-anchor:active, .header-anchor:focus {
outline: none;
}
h1:hover .header-anchor,
h2:hover .header-anchor,
h3:hover .header-anchor,
h4:hover .header-anchor,
h5:hover .header-anchor,
h6:hover .header-anchor {
opacity: 1;
}
.api-reference-menu {
-moz-column-count: 2;
-webkit-column-count: 2;
columns: 2;
margin-bottom: 50px;
}
.post-info {
float: right;
}
.info-box {
margin-top: 20px;
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
padding: 15px;
margin-bottom: 20px;
border: 1px dashed #8a6d3b;
border-radius: 4px;
}
.supporter.reaktor {
width: 200px;
margin: 0px auto;
}
================================================
FILE: docs/css/mono-blue.css
================================================
.highlight {
display: block;
overflow-x: auto;
padding: 0.5em;
margin: 15px 0px;
background: #eaeef3;
-webkit-text-size-adjust: none;
color: #00193a;
}
code {
color: #00193a;
background: #eaeef3;
}
a code {
color: #337AB7;
}
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #738191; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #4c81c9; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .cm { color: #738191; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
.highlight .c1 { color: #738191; font-style: italic } /* Comment.Single */
.highlight .cs { color: #738191; font-style: italic } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #808080 } /* Generic.Output */
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0040D0 } /* Generic.Traceback */
.highlight .kc { color: #4c81c9; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #4c81c9; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #4c81c9; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #4c81c9 } /* Keyword.Pseudo */
.highlight .kr { color: #4c81c9; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #B00040 } /* Keyword.Type */
.highlight .m { color: #666666 } /* Literal.Number */
.highlight .s { color: #BE7306;} /* Literal.String */
.highlight .na { color: #7D9029 } /* Name.Attribute */
.highlight .nb { color: #4c81c9 } /* Name.Builtin */
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.highlight .no { color: #880000 } /* Name.Constant */
.highlight .nd { color: #AA22FF } /* Name.Decorator */
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0000FF } /* Name.Function */
.highlight .nl { color: #A0A000 } /* Name.Label */
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #4c81c9; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #19177C } /* Name.Variable */
.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #666666 } /* Literal.Number.Float */
.highlight .mh { color: #666666 } /* Literal.Number.Hex */
.highlight .mi { color: #666666 } /* Literal.Number.Integer */
.highlight .mo { color: #666666 } /* Literal.Number.Oct */
.highlight .sb { color: #BE7306 } /* Literal.String.Backtick */
.highlight .sc { color: #BE7306 } /* Literal.String.Char */
.highlight .sd { color: #BE7306; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #BE7306 } /* Literal.String.Double */
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #BE7306 } /* Literal.String.Heredoc */
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.highlight .sx { color: #BE7306 } /* Literal.String.Other */
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
.highlight .s1 { color: #BE7306 } /* Literal.String.Single */
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
.highlight .bp { color: #4c81c9 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #19177C } /* Name.Variable.Class */
.highlight .vg { color: #19177C } /* Name.Variable.Global */
.highlight .vi { color: #19177C } /* Name.Variable.Instance */
.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */
================================================
FILE: docs/docs/anti-patterns.md
================================================
---
id: anti-patterns
title: Anti-patterns
---
This page will contain common promise anti-patterns that are exercised in the wild.
- [The explicit construction anti-pattern](#the-explicit-construction-anti-pattern)
- [The `.then(success, fail)` anti-pattern](#the-.then)
##The Explicit Construction Anti-Pattern
This is the most common anti-pattern. It is easy to fall into this when you don't really understand promises and think of them as glorified event emitters or callback utility. It's also sometimes called the promise constructor anti-pattern. Let's recap: promises are about making asynchronous code retain most of the lost properties of synchronous code such as flat indentation and one exception channel. This pattern is also called the deferred anti-pattern.
In the explicit construction anti-pattern, promise objects are created for no reason, complicating code.
First example is creating deferred object when you already have a promise or thenable:
```js
//Code copyright by Twisternha http://stackoverflow.com/a/19486699/995876 CC BY-SA 2.5
myApp.factory('Configurations', function (Restangular, MotorRestangular, $q) {
var getConfigurations = function () {
var deferred = $q.defer();
MotorRestangular.all('Motors').getList().then(function (Motors) {
//Group by Config
var g = _.groupBy(Motors, 'configuration');
//Map values
var mapped = _.map(g, function (m) {
return {
id: m[0].configuration,
configuration: m[0].configuration,
sizes: _.map(m, function (a) {
return a.sizeMm
})
}
});
deferred.resolve(mapped);
});
return deferred.promise;
};
return {
config: getConfigurations()
}
});
```
This superfluous wrapping is also dangerous, any kind of errors and rejections are swallowed and not propagated to the caller of this function.
Instead of using the Deferred anti-pattern, the code should simply return the promise it already has and propagate values using `return`:
```js
myApp.factory('Configurations', function (Restangular, MotorRestangular, $q) {
var getConfigurations = function () {
//Just return the promise we already have!
return MotorRestangular.all('Motors').getList().then(function (Motors) {
//Group by Cofig
var g = _.groupBy(Motors, 'configuration');
//Return the mapped array as the value of this promise
return _.map(g, function (m) {
return {
id: m[0].configuration,
configuration: m[0].configuration,
sizes: _.map(m, function (a) {
return a.sizeMm
})
}
});
});
};
return {
config: getConfigurations()
}
});
```
Not only is the code shorter but more importantly, if there is any error it will propagate properly to the final consumer.
Second example is creating a function that does nothing but manually wrap a callback API and doing a poor job at that:
```js
function applicationFunction(arg1) {
return new Promise(function(resolve, reject){ //Or Q.defer() in Q
libraryFunction(arg1, function (err, value) {
if (err) {
reject(err);
} else {
resolve(value);
}
});
}
```
This is reinventing the square wheel because any callback API wrapping can and should be done immediately using the promise library's promisification methods:
```js
var applicationFunction = Promise.promisify(libraryFunction);
```
The generic promisification is likely to be faster because it can use internals directly but also handles edge cases like `libraryFunction` throwing synchronously or using multiple success values.
**So when should deferred be used?**
Well simply, when you have to.
You might have to use a deferred object when wrapping a callback API that doesn't follow the standard convention. Like `setTimeout`:
```js
//setTimeout that returns a promise
function delay(ms) {
var deferred = Promise.defer(); // warning, defer is deprecated, use the promise constructor
setTimeout(function(){
deferred.fulfill();
}, ms);
return deferred.promise;
}
```
Such wrappers should be rare, if they're common for the reason that the promise library cannot generically promisify them, you should file an issue.
If you cannot do static promisification (promisify and promisifyAll perform too slowly to use at runtime), you may use [Promise.fromCallback](.).
Also see [this StackOverflow question](http://stackoverflow.com/questions/23803743/what-is-the-deferred-antipattern-and-how-do-i-avoid-it) for more examples and a debate around it.
##The `.then(success, fail)` anti-pattern
*Almost* a sure sign of using promises as glorified callbacks. Instead of `doThat(function(err, success))` you do `doThat().then(success, err)` and rationalize to yourself that at least the code is "less coupled" or something.
The `.then` signature is mostly about interop, there is *almost* never a reason to use `.then(success, fail)` in application code. It is even awkward to express it in the sync parallel:
```js
var t0;
try {
t0 = doThat();
}
catch(e) {
}
//deal with t0 here and waste the try-catch
var stuff = JSON.parse(t0);
```
It is more likely that you would write this instead in the sync world:
```js
try {
var stuff = JSON.parse(doThat());
}
catch(e) {
}
```
So please write the same when using promises too:
```js
doThat()
.then(function(v) {
return JSON.parse(v);
})
.catch(function(e) {
});
```
`.catch` is specified for built-in Javascript promises and is "sugar" for `.then(null, function(){})`. Since the way errors work in promises is almost the entire point (and the only thing jQuery never got right, even if it used `.pipe` as a `.then`), I really hope the implementation you are using provides this method for readability.
================================================
FILE: docs/docs/api/aggregateerror.md
================================================
---
layout: api
id: aggregateerror
title: AggregateError
---
[← Back To API Reference](/docs/api-reference.html)
##AggregateError
```js
new AggregateError() extends Array -> AggregateError
```
A collection of errors. `AggregateError` is an array-like object, with numeric indices and a `.length` property. It supports all generic array methods such as `.forEach` directly.
`AggregateError`s are caught in [`.error`](.) handlers, even if the contained errors are not operational.
[Promise.some](.) and [Promise.any](.) use `AggregateError` as rejection reason when they fail.
Example:
```js
//Assumes AggregateError has been made global
var err = new AggregateError();
err.push(new Error("first error"));
err.push(new Error("second error"));
throw err;
```
================================================
FILE: docs/docs/api/all.md
================================================
---
layout: api
id: all
title: .all
---
[← Back To API Reference](/docs/api-reference.html)
##.all
```js
.all() -> Promise
```
Consume the resolved [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) and wait for all items to fulfill similar to [Promise.all()](.).
[Promise.resolve(iterable).all()](.) is the same as [Promise.all(iterable)](.).
================================================
FILE: docs/docs/api/any.md
================================================
---
layout: api
id: any
title: .any
---
[← Back To API Reference](/docs/api-reference.html)
##.any
```js
.any() -> Promise
```
Same as [Promise.any(this)](.).
================================================
FILE: docs/docs/api/ascallback.md
================================================
---
layout: api
id: ascallback
title: .asCallback
---
[← Back To API Reference](/docs/api-reference.html)
##.asCallback
```js
.asCallback(
[function(any error, any value) callback],
[Object {spread: boolean=false} options]
) -> this
```
```js
.nodeify(
[function(any error, any value) callback],
[Object {spread: boolean=false} options]
) -> this
```
Register a node-style callback on this promise. When this promise is either fulfilled or rejected, the node callback will be called back with the node.js convention where error reason is the first argument and success value is the second argument. The error argument will be `null` in case of success.
Returns back this promise instead of creating a new one. If the `callback` argument is not a function, this method does not do anything.
This can be used to create APIs that both accept node-style callbacks and return promises:
```js
function getDataFor(input, callback) {
return dataFromDataBase(input).asCallback(callback);
}
```
The above function can then make everyone happy.
Promises:
```js
getDataFor("me").then(function(dataForMe) {
console.log(dataForMe);
});
```
Normal callbacks:
```js
getDataFor("me", function(err, dataForMe) {
if( err ) {
console.error( err );
}
console.log(dataForMe);
});
```
Promises can be rejected with falsy values (or no value at all, equal to rejecting with `undefined`), however `.asCallback` will call the callback with an `Error` object if the promise's rejection reason is a falsy value. You can retrieve the original falsy value from the error's `.cause` property.
Example:
```js
Promise.reject(null).asCallback(function(err, result) {
// If is executed
if (err) {
// Logs 'null'
console.log(err.cause);
}
});
```
There is no effect on performance if the user doesn't actually pass a node-style callback function.
####Option: spread
Some nodebacks expect more than 1 success value but there is no mapping for this in the promise world. You may specify the option `spread` to call the nodeback with multiple values when the fulfillment value is an array:
```js
Promise.resolve([1,2,3]).asCallback(function(err, result) {
// err == null
// result is the array [1,2,3]
});
Promise.resolve([1,2,3]).asCallback(function(err, a, b, c) {
// err == null
// a == 1
// b == 2
// c == 3
}, {spread: true});
Promise.resolve(123).asCallback(function(err, a, b, c) {
// err == null
// a == 123
// b == undefined
// c == undefined
}, {spread: true});
```
================================================
FILE: docs/docs/api/bind.md
================================================
---
layout: api
id: bind
title: .bind
---
[← Back To API Reference](/docs/api-reference.html)
##.bind
```js
.bind(any|Promise thisArg) -> BoundPromise
```
Same as calling [Promise.bind(thisArg, thisPromise)](.).
================================================
FILE: docs/docs/api/built-in-error-types.md
================================================
---
layout: api
id: built-in-error-types
title: Built-in error types
---
[← Back To API Reference](/docs/api-reference.html)
##Built-in error types
Bluebird includes a few built-in error types for common usage. All error types have the same identity across different copies of bluebird
module so that pattern matching works in [`.catch`](.). All error types have a constructor taking a message string as their first argument, with that message
becoming the `.message` property of the error object.
By default the error types need to be referenced from the Promise constructor, e.g. to get a reference to [TimeoutError](.), do `var TimeoutError = Promise.TimeoutError`. However, for convenience you will probably want to just make the references global.
================================================
FILE: docs/docs/api/call.md
================================================
---
layout: api
id: call
title: .call
---
[← Back To API Reference](/docs/api-reference.html)
##.call
```js
.call(
String methodName,
[any args...]
)
```
This is a convenience method for doing:
```js
promise.then(function(obj) {
return obj[methodName].call(obj, arg...);
});
```
For example ([`some` is a built-in array method](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/some)):
```js
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var path = require("path");
var thisPath = process.argv[2] || ".";
var now = Date.now();
fs.readdirAsync(thisPath)
.map(function(fileName) {
return fs.statAsync(path.join(thisPath, fileName));
})
.call("some", function(stat) {
return (now - new Date(stat.mtime)) < 10000;
})
.then(function(someFilesHaveBeenModifiedLessThanTenSecondsAgo) {
console.log(someFilesHaveBeenModifiedLessThanTenSecondsAgo) ;
});
```
Chaining lo-dash or underscore methods (Copy-pasteable example):
```js
var Promise = require("bluebird");
var pmap = Promise.map;
var props = Promise.props;
var _ = require("lodash");
var fs = Promise.promisifyAll(require("fs"));
function getTotalSize(paths) {
return pmap(paths, function(path) {
return fs.statAsync(path).get("size");
}).reduce(function(a, b) {
return a + b;
}, 0);
}
fs.readdirAsync(".").then(_)
.call("groupBy", function(fileName) {
return fileName.charAt(0);
})
.call("map", function(fileNames, firstCh) {
return props({
firstCh: firstCh,
count: fileNames.length,
totalSize: getTotalSize(fileNames)
});
})
// Since the currently wrapped array contains promises we need to unwrap it and call .all() before continuing the chain
// If the currently wrapped thing was an object with properties that might be promises, we would call .props() instead
.call("value").all().then(_)
.call("sortBy", "count")
.call("reverse")
.call("map", function(data) {
return data.count + " total files beginning with " + data.firstCh + " with total size of " + data.totalSize + " bytes";
})
.call("join", "\n")
.then(console.log)
```
================================================
FILE: docs/docs/api/cancel.md
================================================
---
layout: api
id: cancel
title: .cancel
---
[← Back To API Reference](/docs/api-reference.html)
##.cancel
```js
.cancel() -> undefined
```
Cancel this promise. Will not do anything if this promise is already settled or if the [Cancellation](.) feature has not been enabled. See [Cancellation](.) for how to use cancellation.
================================================
FILE: docs/docs/api/cancellation.md
================================================
---
layout: api
id: cancellation
title: Cancellation
---
[← Back To API Reference](/docs/api-reference.html)
##Cancellation
Cancellation has been redesigned for bluebird 3.x, any code that relies on 2.x cancellation semantics won't work in 3.x.
The cancellation feature is **by default turned off**, you can enable it using [Promise.config](.).
The new cancellation has "don't care" semantics while the old cancellation had abort semantics. Cancelling a promise simply means that its handler callbacks will not be called.
The advantages of the new cancellation compared to the old cancellation are:
- [.cancel()](.) is synchronous.
- no setup code required to make cancellation work
- composes with other bluebird features, like [Promise.all](.).
- [reasonable semantics for multiple consumer cancellation](#what-about-promises-that-have-multiple-consumers)
As an optimization, the cancellation signal propagates upwards the promise chain so that an ongoing operation e.g. network request can be aborted. However, *not* aborting the network request still doesn't make any operational difference as the callbacks are still not called either way.
You may register an optional cancellation hook at a root promise by using the `onCancel` argument that is passed to the executor function when cancellation is enabled:
```js
function makeCancellableRequest(url) {
return new Promise(function(resolve, reject, onCancel) {
var xhr = new XMLHttpRequest();
xhr.on("load", resolve);
xhr.on("error", reject);
xhr.open("GET", url, true);
xhr.send(null);
// Note the onCancel argument only exists if cancellation has been enabled!
onCancel(function() {
xhr.abort();
});
});
}
```
Note that the `onCancel` hook is really an optional disconnected optimization, there is no real requirement to register any cancellation hooks for cancellation to work. As such, any errors that may occur while inside the `onCancel` callback are not caught and turned into rejections.
While `cancel().` is synchronous - `onCancel()` is called asynchronously (in the next turn) just like `then` handlers.
Example:
```js
var searchPromise = Promise.resolve(); // Dummy promise to avoid null check.
document.querySelector("#search-input").addEventListener("input", function() {
// The handlers of the previous request must not be called
searchPromise.cancel();
var url = "/search?term=" + encodeURIComponent(this.value.trim());
showSpinner();
searchPromise = makeCancellableRequest(url)
.then(function(results) {
return transformData(results);
})
.then(function(transformedData) {
document.querySelector("#search-results").innerHTML = transformedData;
})
.catch(function(e) {
document.querySelector("#search-results").innerHTML = renderErrorBox(e);
})
.finally(function() {
// This check is necessary because `.finally` handlers are always called.
if (!searchPromise.isCancelled()) {
hideSpinner();
}
});
});
```
As shown in the example the handlers registered with `.finally` are called even if the promise is cancelled. Another such exception is [.reflect()](.). No other types of handlers will be called in case of cancellation. This means that in `.then(onSuccess, onFailure)` neither `onSuccess` or `onFailure` handler is called. This is similar to how [`Generator#return`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) works - only active `finally` blocks are executed and then the generator exits.
###What about promises that have multiple consumers?
It is often said that promises cannot be cancellable because they can have multiple consumers.
For instance:
```js
var result = makeCancellableRequest(...);
var firstConsumer = result.then(...);
var secondConsumer = result.then(...);
```
Even though in practice most users of promises will never have any need to take advantage of the fact that you can attach multiple consumers to a promise, it is nevertheless possible. The problem: "what should happen if [.cancel()](.) is called on `firstConsumer`?" Propagating the cancellation signal (and therefore making it abort the request) would be very bad as the second consumer might still be interested in the result despite the first consumer's disinterest.
What actually happens is that `result` keeps track of how many consumers it has, in this case 2, and only if all the consumers signal cancel will the request be aborted. However, as far as `firstConsumer` can tell, the promise was successfully cancelled and its handlers will not be called.
Note that it is an error to consume an already cancelled promise, doing such a thing will give you a promise that is rejected with `new CancellationError("late cancellation observer")` as the rejection reason.
================================================
FILE: docs/docs/api/cancellationerror.md
================================================
---
layout: api
id: cancellationerror
title: CancellationError
---
[← Back To API Reference](/docs/api-reference.html)
##CancellationError
```js
new CancellationError(String message) -> CancellationError
```
Signals that an operation has been aborted or cancelled. The default reason used by [`.cancel`](.).
================================================
FILE: docs/docs/api/catch.md
================================================
---
layout: api
id: catch
title: .catch
---
[← Back To API Reference](/docs/api-reference.html)
##.catch
`.catch` is a convenience method for handling errors in promise chains.
It comes in two variants
- A catch-all variant similar to the synchronous `catch(e) {` block. This variant is compatible with native promises.
- A filtered variant (like other non-JS languages typically have) that lets you only handle specific errors. **This variant is usually preferable and is significantly safer**.
### A note on promise exception handling.
Promise exception handling mirrors native exception handling in JavaScript. A synchronous function `throw`ing is similar to a promise rejecting. Here is an example to illustrate it:
```js
function getItems(param) {
try {
var items = getItemsSync();
if(!items) throw new InvalidItemsError();
} catch(e) {
// can address the error here, either from getItemsSync returning a falsey value or throwing itself
throw e; // need to re-throw the error unless I want it to be considered handled.
}
return process(items);
}
```
Similarly, with promises:
```js
function getItems(param) {
return getItemsAsync().then(items => {
if(!items) throw new InvalidItemsError();
return items;
}).catch(e => {
// can address the error here and recover from it, from getItemsAsync rejects or returns a falsey value
throw e; // Need to rethrow unless we actually recovered, just like in the synchronous version
}).then(process);
}
```
### Catch-all
```js
.catch(function(any error) handler) -> Promise
```
```js
.caught(function(any error) handler) -> Promise
```
This is a catch-all exception handler, shortcut for calling [`.then(null, handler)`](.) on this promise. Any exception happening in a `.then`-chain will propagate to nearest `.catch` handler.
*For compatibility with earlier ECMAScript versions, an alias `.caught` is provided for [`.catch`](.).*
### Filtered Catch
```js
.catch(
class ErrorClass|function(any error)|Object predicate...,
function(any error) handler
) -> Promise
```
```js
.caught(
class ErrorClass|function(any error)|Object predicate...,
function(any error) handler
) -> Promise
```
This is an extension to [`.catch`](.) to work more like catch-clauses in languages like Java or C#. Instead of manually checking `instanceof` or `.name === "SomeError"`, you may specify a number of error constructors which are eligible for this catch handler. The catch handler that is first met that has eligible constructors specified, is the one that will be called.
Example:
```js
somePromise.then(function() {
return a.b.c.d();
}).catch(TypeError, function(e) {
//If it is a TypeError, will end up here because
//it is a type error to reference property of undefined
}).catch(ReferenceError, function(e) {
//Will end up here if a was never declared at all
}).catch(function(e) {
//Generic catch-the rest, error wasn't TypeError nor
//ReferenceError
});
```
You may also add multiple filters for a catch handler:
```js
somePromise.then(function() {
return a.b.c.d();
}).catch(TypeError, ReferenceError, function(e) {
//Will end up here on programmer error
}).catch(NetworkError, TimeoutError, function(e) {
//Will end up here on expected everyday network errors
}).catch(function(e) {
//Catch any unexpected errors
});
```
For a parameter to be considered a type of error that you want to filter, you need the constructor to have its `.prototype` property be `instanceof Error`.
Such a constructor can be minimally created like so:
```js
function MyCustomError() {}
MyCustomError.prototype = Object.create(Error.prototype);
```
Using it:
```js
Promise.resolve().then(function() {
throw new MyCustomError();
}).catch(MyCustomError, function(e) {
//will end up here now
});
```
However if you want stack traces and cleaner string output, then you should do:
*in Node.js and other V8 environments, with support for `Error.captureStackTrace`*
```js
function MyCustomError(message) {
this.message = message;
this.name = "MyCustomError";
Error.captureStackTrace(this, MyCustomError);
}
MyCustomError.prototype = Object.create(Error.prototype);
MyCustomError.prototype.constructor = MyCustomError;
```
Using CoffeeScript's `class` for the same:
```coffee
class MyCustomError extends Error
constructor: (@message) ->
@name = "MyCustomError"
Error.captureStackTrace(this, MyCustomError)
```
This method also supports predicate-based filters. If you pass a
predicate function instead of an error constructor, the predicate will receive
the error as an argument. The return result of the predicate will be used
determine whether the error handler should be called.
Predicates should allow for very fine grained control over caught errors:
pattern matching, error-type sets with set operations and many other techniques
can be implemented on top of them.
Example of using a predicate-based filter:
```js
var Promise = require("bluebird");
var request = Promise.promisify(require("request"));
function ClientError(e) {
return e.code >= 400 && e.code < 500;
}
request("http://www.google.com").then(function(contents) {
console.log(contents);
}).catch(ClientError, function(e) {
//A client error like 400 Bad Request happened
});
```
Predicate functions that only check properties have a handy shorthand. In place of a predicate function, you can pass an object, and its properties will be checked against the error object for a match:
```js
fs.readFileAsync(...)
.then(...)
.catch({code: 'ENOENT'}, function(e) {
console.log("file not found: " + e.path);
});
```
The object predicate passed to `.catch` in the above code (`{code: 'ENOENT'}`) is shorthand for a predicate function `function predicate(e) { return isObject(e) && e.code == 'ENOENT' }`, I.E. loose equality is used.
*For compatibility with earlier ECMAScript version, an alias `.caught` is provided for [`.catch`](.).*
By not returning a rejected value or `throw`ing from a catch, you "recover from failure" and continue the chain:
```js
Promise.reject(Error('fail!'))
.catch(function(e) {
// fallback with "recover from failure"
return Promise.resolve('success!'); // promise or value
})
.then(function(result) {
console.log(result); // will print "success!"
});
```
This is exactly like the synchronous code:
```js
var result;
try {
throw Error('fail');
} catch(e) {
result = 'success!';
}
console.log(result);
```
================================================
FILE: docs/docs/api/catchreturn.md
================================================
---
layout: api
id: catchreturn
title: .catchReturn
---
[← Back To API Reference](/docs/api-reference.html)
##.catchReturn
```js
.catchReturn(
[class ErrorClass|function(any error) predicate],
any value
) -> Promise
```
Convenience method for:
```js
.catch(function() {
return value;
});
```
You may optionally prepend one predicate function or ErrorClass to pattern match the error (the generic [.catch](.) methods accepts multiple)
Same limitations regarding to the binding time of `value` to apply as with [`.return`](.).
================================================
FILE: docs/docs/api/catchthrow.md
================================================
---
layout: api
id: catchthrow
title: .catchThrow
---
[← Back To API Reference](/docs/api-reference.html)
##.catchThrow
```js
.catchThrow(
[class ErrorClass|function(any error) predicate],
any reason
) -> Promise
```
Convenience method for:
```js
.catch(function() {
throw reason;
});
```
You may optionally prepend one predicate function or ErrorClass to pattern match the error (the generic [.catch](.) methods accepts multiple)
Same limitations regarding to the binding time of `reason` to apply as with [`.return`](.).
================================================
FILE: docs/docs/api/collections.md
================================================
---
layout: api
id: collections
title: Collections
---
[← Back To API Reference](/docs/api-reference.html)
##Collections
Methods of `Promise` instances and core static methods of the Promise class to deal with collections of promises or mixed promises and values.
All collection methods have a static equivalent on the Promise object, e.g. `somePromise.map(...)...` is same as `Promise.map(somePromise, ...)...`,
`somePromise.all` is same as [`Promise.all`](.) and so on.
None of the collection methods modify the original input. Holes in arrays are treated as if they were defined with the value `undefined`.
================================================
FILE: docs/docs/api/core.md
================================================
---
layout: api
id: core
title: Core
---
[← Back To API Reference](/docs/api-reference.html)
##Core
Core methods of `Promise` instances and core static methods of the Promise class.
================================================
FILE: docs/docs/api/deferred-migration.md
================================================
---
layout: api
id: deferred-migration
title: Deferred migration
---
[← Back To API Reference](/docs/api-reference.html)
##Deferred migration
Deferreds are deprecated in favor of the promise constructor. If you need deferreds for some reason, you can create them trivially using the constructor:
```js
function defer() {
var resolve, reject;
var promise = new Promise(function() {
resolve = arguments[0];
reject = arguments[1];
});
return {
resolve: resolve,
reject: reject,
promise: promise
};
}
```
For old code that still uses deferred objects, see [the deprecated API docs ](//bluebirdjs.com/docs/deprecated-apis.html#promise-resolution).
================================================
FILE: docs/docs/api/delay.md
================================================
---
layout: api
id: delay
title: .delay
---
[← Back To API Reference](/docs/api-reference.html)
##.delay
```js
.delay(int ms) -> Promise
```
Same as calling [Promise.delay(ms, this)](.).
================================================
FILE: docs/docs/api/disposer.md
================================================
---
layout: api
id: disposer
title: .disposer
---
[← Back To API Reference](/docs/api-reference.html)
##.disposer
```js
.disposer(function(any resource, Promise usingOutcomePromise) disposer) -> Disposer
```
A meta method used to specify the disposer method that cleans up a resource when using [`Promise.using`](/docs/api/promise.using.html).
Returns a Disposer object which encapsulates both the resource as well as the method to clean it up. The user can pass this object to `Promise.using` to get access to the resource when it becomes available, as well as to ensure it's automatically cleaned up.
The second argument passed to a disposer is the result promise of the using block, which you can inspect synchronously.
Example:
```js
// This function doesn't return a promise but a Disposer
// so it's very hard to use it wrong (not passing it to `using`)
function getConnection() {
return db.connect().disposer(function(connection, promise) {
connection.close();
});
}
```
In the above example, the connection returned by `getConnection` can only be
used via `Promise.using`, like so:
```js
function useConnection(query) {
return Promise.using(getConnection(), function(connection) {
return connection.sendQuery(query).then(function(results) {
return process(results);
})
});
}
```
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.
Real example:
```js
var pg = require("pg");
// Uncomment if pg has not been properly promisified yet
//var Promise = require("bluebird");
//Promise.promisifyAll(pg, {
// filter: function(methodName) {
// return methodName === "connect"
// },
// multiArgs: true
//});
// Promisify rest of pg normally
//Promise.promisifyAll(pg);
function getSqlConnection(connectionString) {
var close;
return pg.connectAsync(connectionString).spread(function(client, done) {
close = done;
return client;
}).disposer(function() {
if (close) close();
});
}
module.exports = getSqlConnection;
```
Real example 2:
```js
var mysql = require("mysql");
// Uncomment if mysql has not been properly promisified yet
// var Promise = require("bluebird");
// Promise.promisifyAll(mysql);
// Promise.promisifyAll(require("mysql/lib/Connection").prototype);
// Promise.promisifyAll(require("mysql/lib/Pool").prototype);
var pool = mysql.createPool({
connectionLimit: 10,
host: 'example.org',
user: 'bob',
password: 'secret'
});
function getSqlConnection() {
return pool.getConnectionAsync().disposer(function(connection) {
connection.release();
});
}
module.exports = getSqlConnection;
```
#### Note about disposers in node
If a disposer method throws or returns a rejected promise, it's highly likely that it failed to dispose of the resource. In that case, Bluebird has two options - it can either ignore the error and continue with program execution or throw an exception (crashing the process in node.js).
In bluebird we've chosen to do the latter because resources are typically scarce. For example, if a database connection cannot be disposed of and Bluebird ignores that, the connection pool will be quickly depleted and the process will become unusable (all requests that query the database will wait forever). Since Bluebird doesn't know how to handle that, the only sensible default is to crash the process. That way, rather than getting a useless process that cannot fulfill more requests, we can swap the faulty worker with a new one letting the OS clean up the resources for us.
As a result, if you anticipate thrown errors or promise rejections while disposing of the resource you should use a `try..catch` block (or Promise.try) and write the appropriate catch code to handle the errors. If it's not possible to sensibly handle the error, letting the process crash is the next best option.
This also means that disposers should not contain code that does anything other than resource disposal. For example, you cannot write code inside a disposer to commit or rollback a transaction, because there is no mechanism for the disposer to signal a failure of the commit or rollback action without crashing the process.
For transactions, you can use the following similar pattern instead:
```js
function withTransaction(fn) {
return Promise.using(pool.acquireConnection(), function(connection) {
var tx = connection.beginTransaction()
return Promise
.try(fn, tx)
.then(function(res) { return connection.commit().thenReturn(res) },
function(err) {
return connection.rollback()
.catch(function(e) {/* maybe add the rollback error to err */})
.thenThrow(err);
});
});
}
// If the withTransaction block completes successfully, the transaction is automatically committed
// Any error or rejection will automatically roll it back
withTransaction(function(tx) {
return tx.queryAsync(...).then(function() {
return tx.queryAsync(...)
}).then(function() {
return tx.queryAsync(...)
});
});
```
================================================
FILE: docs/docs/api/done.md
================================================
---
layout: api
id: done
title: .done
---
[← Back To API Reference](/docs/api-reference.html)
##.done
```js
.done(
[function(any value) fulfilledHandler],
[function(any error) rejectedHandler]
) -> undefined
```
Like [`.then`](.), but any unhandled rejection that ends up here will crash the process (in node) or be thrown as an error (in browsers). The use of this method is heavily discouraged and it only exists for historical reasons.
================================================
FILE: docs/docs/api/each.md
================================================
---
layout: api
id: each
title: .each
---
[← Back To API Reference](/docs/api-reference.html)
##.each
```js
.each(function(any item, int index, int length) iterator) -> Promise
```
Iterate over an array, or a promise of an array, which contains promises (or a mix of promises and values) with the given `iterator` function with the signature `(value, index, length)` where `value` is the resolved value of a respective promise in the input array. Iteration happens serially. If any promise in the input array is rejected the returned promise is rejected as well.
Resolves to the original array unmodified, this method is meant to be used for side effects. If the iterator function returns a promise or a thenable, then the result of the promise is awaited, before continuing with next iteration.
Example where you might want to utilize `.each`:
```js
// Source: http://jakearchibald.com/2014/es7-async-functions/
function loadStory() {
return getJSON('story.json')
.then(function(story) {
addHtmlToPage(story.heading);
return story.chapterURLs.map(getJSON);
})
.each(function(chapter) { addHtmlToPage(chapter.html); })
.then(function() { addTextToPage("All done"); })
.catch(function(err) { addTextToPage("Argh, broken: " + err.message); })
.then(function() { document.querySelector('.spinner').style.display = 'none'; });
}
```
================================================
FILE: docs/docs/api/environment-variables.md
================================================
---
layout: api
id: environment-variables
title: Environment variables
---
[← Back To API Reference](/docs/api-reference.html)
##Environment variables
This section only applies to node.js or io.js.
You can change bluebird behavior globally with various environment variables. These global variables affect all instances of bluebird that are running in your environment, rather than just the one you have `require`d in your application. The effect an environment variable has depends on the bluebird version.
Environment variables supported by 2.x:
- `BLUEBIRD_DEBUG` - Set to any truthy value this will enable long stack traces and warnings
- `NODE_ENV` - If set exactly to `development` it will have the same effect as if the `BLUEBIRD_DEBUG` variable was set.
Environment variables supported by 3.x:
- `BLUEBIRD_DEBUG` - If set this will enable long stack traces and warnings, unless those are explicitly disabled. Setting this to exactly `0` can be used to override `NODE_ENV=development` enabling long stack traces and warnings.
- `NODE_ENV` - If set exactly to `development` it will have the same effect as if the `BLUEBIRD_DEBUG` variable was set.
- `BLUEBIRD_WARNINGS` - if set exactly to `0` it will explicitly disable warnings and this overrides any other setting that might enable warnings. If set to any truthy value, it will explicitly enable warnings.
- `BLUEBIRD_LONG_STACK_TRACES` - if set exactly to `0` it will explicitly disable long stack traces and this overrides any other setting that might enable long stack traces. If set to any truthy value, it will explicitly enable long stack traces.
================================================
FILE: docs/docs/api/error-management-configuration.md
================================================
---
layout: api
id: error-management-configuration
title: Error management configuration
---
[← Back To API Reference](/docs/api-reference.html)
##Error management configuration
The default approach of bluebird is to immediately log the stack trace when there is an unhandled rejection. This is similar to how uncaught exceptions cause the stack trace to be logged so that you have something to work with when something is not working as expected.
However because it is possible to handle a rejected promise at any time in the indeterminate future, some programming patterns will result in false positives. Because such programming patterns are not necessary and can always be refactored to never cause false positives, we recommend doing that to keep debugging as easy as possible . You may however feel differently so bluebird provides hooks to implement more complex failure policies.
Such policies could include:
- Logging after the promise became GCd (requires a native node.js module)
- Showing a live list of rejected promises
- Using no hooks and using [`.done`](.) to manually to mark end points where rejections will not be handled
- Swallowing all errors (challenge your debugging skills)
- ...
###Global rejection events
Starting from 2.7.0 all bluebird instances also fire rejection events globally so that applications can register one universal hook for them.
The global events are:
- `"unhandledRejection"` (corresponds to the local [`Promise.onPossiblyUnhandledRejection`](.))
- `"rejectionHandled"` (corresponds to the local [`Promise.onUnhandledRejectionHandled`](.))
Attaching global rejection event handlers in **node.js**:
```js
// NOTE: event name is camelCase as per node convention
process.on("unhandledRejection", function(reason, promise) {
// See Promise.onPossiblyUnhandledRejection for parameter documentation
});
// NOTE: event name is camelCase as per node convention
process.on("rejectionHandled", function(promise) {
// See Promise.onUnhandledRejectionHandled for parameter documentation
});
```
Attaching global rejection event handlers in **browsers**:
Using DOM3 `addEventListener` APIs (support starting from IE9+):
```js
// NOTE: event name is all lower case as per DOM convention
window.addEventListener("unhandledrejection", function(e) {
// NOTE: e.preventDefault() must be manually called to prevent the default
// action which is currently to log the stack trace to console.warn
e.preventDefault();
// NOTE: parameters are properties of the event detail property
var reason = e.detail.reason;
var promise = e.detail.promise;
// See Promise.onPossiblyUnhandledRejection for parameter documentation
});
// NOTE: event name is all lower case as per DOM convention
window.addEventListener("rejectionhandled", function(e) {
// NOTE: e.preventDefault() must be manually called prevent the default
// action which is currently unset (but might be set to something in the future)
e.preventDefault();
// NOTE: parameters are properties of the event detail property
var promise = e.detail.promise;
// See Promise.onUnhandledRejectionHandled for parameter documentation
});
```
In Web Workers you may use `self.addEventListener`.
Using legacy APIs (support starting from IE6+):
```js
// NOTE: event name is all lower case as per legacy convention
window.onunhandledrejection = function(reason, promise) {
// See Promise.onPossiblyUnhandledRejection for parameter documentation
};
// NOTE: event name is all lower case as per legacy convention
window.onrejectionhandled = function(promise) {
// See Promise.onUnhandledRejectionHandled for parameter documentation
};
```
================================================
FILE: docs/docs/api/error.md
================================================
---
layout: api
id: error
title: .error
---
[← Back To API Reference](/docs/api-reference.html)
##.error
```js
.error([function(any error) rejectedHandler]) -> Promise
```
Like [`.catch`](.) but instead of catching all types of exceptions, it only catches operational errors.
*Note, "errors" mean errors, as in objects that are `instanceof Error` - not strings, numbers and so on. See [a string is not an error](http://www.devthought.com/2011/12/22/a-string-is-not-an-error/).*
It is equivalent to the following [`.catch`](.) pattern:
```js
// Assumes OperationalError has been made global
function isOperationalError(e) {
if (e == null) return false;
return (e instanceof OperationalError) || (e.isOperational === true);
}
// Now this bit:
.catch(isOperationalError, function(e) {
// ...
})
// Is equivalent to:
.error(function(e) {
// ...
});
```
For example, if a promisified function errbacks the node-style callback with an error, that could be caught with [`.error`](.). However if the node-style callback **throws** an error, only `.catch` would catch that.
In the following example you might want to handle just the `SyntaxError` from JSON.parse and Filesystem errors from `fs` but let programmer errors bubble as unhandled rejections:
```js
var fs = Promise.promisifyAll(require("fs"));
fs.readFileAsync("myfile.json").then(JSON.parse).then(function (json) {
console.log("Successful json")
}).catch(SyntaxError, function (e) {
console.error("file contains invalid json");
}).error(function (e) {
console.error("unable to read file, because: ", e.message);
});
```
Now, because there is no catch-all handler, if you typed `console.lag` (causes an error you don't expect), you will see:
```
Possibly unhandled TypeError: Object # has no method 'lag'
at application.js:8:13
From previous event:
at Object. (application.js:7:4)
at Module._compile (module.js:449:26)
at Object.Module._extensions..js (module.js:467:10)
at Module.load (module.js:349:32)
at Function.Module._load (module.js:305:12)
at Function.Module.runMain (module.js:490:10)
at startup (node.js:121:16)
at node.js:761:3
```
*( If you don't get the above - you need to enable [long stack traces](/docs/api/promise.config.html) )*
And if the file contains invalid JSON:
```
file contains invalid json
```
And if the `fs` module causes an error like file not found:
```
unable to read file, because: ENOENT, open 'not_there.txt'
```
================================================
FILE: docs/docs/api/filter.md
================================================
---
layout: api
id: filter
title: .filter
---
[← Back To API Reference](/docs/api-reference.html)
##.filter
```js
.filter(
function(any item, int index, int length) filterer,
[Object {concurrency: int=Infinity} options]
) -> Promise
```
Same as [Promise.filter(this, filterer, options)](.).
================================================
FILE: docs/docs/api/finally.md
================================================
---
layout: api
id: finally
title: .finally
---
[← Back To API Reference](/docs/api-reference.html)
##.finally
```js
.finally(function() handler) -> Promise
```
```js
.lastly(function() handler) -> Promise
```
Pass a handler that will be called regardless of this promise's fate. Returns a new promise chained from this promise. There are special semantics for [`.finally`](.) in that the final value cannot be modified from the handler.
*Note: using [`.finally`](.) for resource management has better alternatives, see [resource management](/docs/api/resource-management.html)*
Consider the example:
```js
function anyway() {
$("#ajax-loader-animation").hide();
}
function ajaxGetAsync(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.addEventListener("error", reject);
xhr.addEventListener("load", resolve);
xhr.open("GET", url);
xhr.send(null);
}).then(anyway, anyway);
}
```
This example doesn't work as intended because the `then` handler actually swallows the exception and returns `undefined` for any further chainers.
The situation can be fixed with `.finally`:
```js
function ajaxGetAsync(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.addEventListener("error", reject);
xhr.addEventListener("load", resolve);
xhr.open("GET", url);
xhr.send(null);
}).finally(function() {
$("#ajax-loader-animation").hide();
});
}
```
Now the animation is hidden but, unless it throws an exception, the function has no effect on the fulfilled or rejected value of the returned promise. This is similar to how the synchronous `finally` keyword behaves.
If the handler function passed to `.finally` returns a promise, the promise returned by `.finally` will not be settled until the promise returned by the handler is settled. If the handler fulfills its promise, the returned promise will be fulfilled or rejected with the original value. If the handler rejects its promise, the returned promise will be rejected with the handler's value. This is similar to throwing an exception in a synchronous `finally` block, causing the original value or exception to be forgotten. This delay can be useful if the actions performed by the handler are done asynchronously. For example:
```js
function ajaxGetAsync(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.addEventListener("error", reject);
xhr.addEventListener("load", resolve);
xhr.open("GET", url);
xhr.send(null);
}).finally(function() {
return Promise.fromCallback(function(callback) {
$("#ajax-loader-animation").fadeOut(1000, callback);
});
});
}
```
If the fade out completes successfully, the returned promise will be fulfilled or rejected with the value from `xhr`. If `.fadeOut` throws an exception or passes an error to the callback, the returned promise will be rejected with the error from `.fadeOut`.
*For compatibility with earlier ECMAScript version, an alias `.lastly` is provided for [`.finally`](.).*
================================================
FILE: docs/docs/api/generators.md
================================================
---
layout: api
id: generators
title: Generators
---
[← Back To API Reference](/docs/api-reference.html)
##Generators
Using ECMAScript6 generators feature to implement C# 5.0 `async/await` like syntax.
================================================
FILE: docs/docs/api/get.md
================================================
---
layout: api
id: get
title: .get
---
[← Back To API Reference](/docs/api-reference.html)
##.get
```js
.get(String propertyName|int index) -> Promise
```
This is a convenience method for doing:
```js
promise.then(function(obj) {
return obj[propertyName];
});
```
For example:
```js
db.query("...")
.get(0)
.then(function(firstRow) {
});
```
If `index` is negative, the indexed load will become `obj.length + index`. So that -1 can be used to read last item
in the array, -2 to read the second last and so on. For example:
```js
Promise.resolve([1,2,3]).get(-1).then(function(value) {
console.log(value); // 3
});
```
If the `index` is still negative after `obj.length + index`, it will be clamped to 0.
================================================
FILE: docs/docs/api/iscancelled.md
================================================
---
layout: api
id: iscancelled
title: .isCancelled
---
[← Back To API Reference](/docs/api-reference.html)
##.isCancelled
```js
.isCancelled() -> boolean
```
See if this `promise` has been cancelled.
================================================
FILE: docs/docs/api/isfulfilled.md
================================================
---
layout: api
id: isfulfilled
title: .isFulfilled
---
[← Back To API Reference](/docs/api-reference.html)
##.isFulfilled
```js
.isFulfilled() -> boolean
```
See if this promise has been fulfilled.
================================================
FILE: docs/docs/api/ispending.md
================================================
---
layout: api
id: ispending
title: .isPending
---
[← Back To API Reference](/docs/api-reference.html)
##.isPending
```js
.isPending() -> boolean
```
See if this `promise` is pending (not fulfilled or rejected or cancelled).
================================================
FILE: docs/docs/api/isrejected.md
================================================
---
layout: api
id: isrejected
title: .isRejected
---
[← Back To API Reference](/docs/api-reference.html)
##.isRejected
```js
.isRejected() -> boolean
```
See if this promise has been rejected.
================================================
FILE: docs/docs/api/map.md
================================================
---
layout: api
id: map
title: .map
---
[← Back To API Reference](/docs/api-reference.html)
##.map
```js
.map(
function(any item, int index, int length) mapper,
[Object {concurrency: int=Infinity} options]
) -> Promise
```
Same as [Promise.map(this, mapper, options)](.).
================================================
FILE: docs/docs/api/mapseries.md
================================================
---
layout: api
id: mapseries
title: .mapseries
---
[← Back To API Reference](/docs/api-reference.html)
##.mapSeries
```js
.mapSeries(function(any item, int index, int length) mapper) -> Promise
```
Same as [Promise.mapSeries(this, iterator)](.).
================================================
FILE: docs/docs/api/new-promise.md
================================================
---
layout: api
id: new-promise
title: new Promise
---
[← Back To API Reference](/docs/api-reference.html)
##new Promise
```js
new Promise(function(function resolve, function reject) resolver) -> Promise
```
Create a new promise. The passed in function will receive functions `resolve` and `reject` as its arguments which can be called to seal the fate of the created promise.
*Note: See [explicit construction anti-pattern]({{ "/docs/anti-patterns.html#the-explicit-construction-anti-pattern" | prepend: site.baseurl }}) before creating promises yourself*
Example:
```js
function ajaxGetAsync(url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest;
xhr.addEventListener("error", reject);
xhr.addEventListener("load", resolve);
xhr.open("GET", url);
xhr.send(null);
});
}
```
If you pass a promise object to the `resolve` function, the created promise will follow the state of that promise.
To make sure a function that returns a promise is following the implicit but critically important contract of promises, you can start a function with `new Promise` if you cannot start a chain immediately:
```js
function getConnection(urlString) {
return new Promise(function(resolve) {
//Without new Promise, this throwing will throw an actual exception
var params = parse(urlString);
resolve(getAdapter(params).getConnection());
});
}
```
The above ensures `getConnection` fulfills the contract of a promise-returning function of never throwing a synchronous exception. Also see [`Promise.try`](.) and [`Promise.method`](.)
The resolver is called synchronously (the following is for documentation purposes and not idiomatic code):
```js
function getPromiseResolveFn() {
var res;
new Promise(function (resolve) {
res = resolve;
});
// res is guaranteed to be set
return res;
}
```
================================================
FILE: docs/docs/api/operationalerror.md
================================================
---
layout: api
id: operationalerror
title: OperationalError
---
[← Back To API Reference](/docs/api-reference.html)
##OperationalError
```js
new OperationalError(String message) -> OperationalError
```
Represents an error is an explicit promise rejection as opposed to a thrown error. For example, if an error is errbacked by a callback API promisified through [`Promise.promisify`](.) or [`Promise.promisifyAll`](.)
and is not a typed error, it will be converted to a `OperationalError` which has the original error in the `.cause` property.
`OperationalError`s are caught in [`.error`](.) handlers.
================================================
FILE: docs/docs/api/progression-migration.md
================================================
---
layout: api
id: progression-migration
title: Progression migration
---
[← Back To API Reference](/docs/api-reference.html)
##Progression migration
Progression has been removed as there are composability and chaining issues with APIs that use promise progression handlers. Implementing the common use case of progress bars can be accomplished using a pattern similar to [IProgress](http://blogs.msdn.com/b/dotnet/archive/2012/06/06/async-in-4-5-enabling-progress-and-cancellation-in-async-apis.aspx) in C#.
For old code that still uses it, see [the progression docs in the deprecated API documentation](/docs/deprecated-apis.html#progression).
Using jQuery before:
```js
Promise.resolve($.get(...))
.progressed(function() {
// ...
})
.then(function() {
// ...
})
.catch(function(e) {
// ...
})
```
Using jQuery after:
```js
Promise.resolve($.get(...).progress(function() {
// ...
}))
.then(function() {
// ...
})
.catch(function(e) {
// ...
})
```
Implementing general progress interfaces like in C#:
```js
function returnsPromiseWithProgress(progressHandler) {
return doFirstAction().tap(function() {
progressHandler(0.33);
}).then(doSecondAction).tap(function() {
progressHandler(0.66);
}).then(doThirdAction).tap(function() {
progressHandler(1.00);
});
}
returnsPromiseWithProgress(function(progress) {
ui.progressbar.setWidth((progress * 200) + "px"); // update width on client side
}).then(function(value) { // action complete
// entire chain is complete.
}).catch(function(e) {
// error
});
```
Another example using `coroutine`:
```js
var doNothing = function() {};
var progressSupportingCoroutine = Promise.coroutine(function* (progress) {
progress = typeof progress === "function" ? progress : doNothing;
var first = yield getFirstValue();
// 33% done
progress(0.33);
var second = yield getSecondValue();
progress(0.67);
var third = yield getThirdValue();
progress(1);
return [first, second, third];
});
var progressConsumingCoroutine = Promise.coroutine(function* () {
var allValues = yield progressSupportingCoroutine(function(p) {
ui.progressbar.setWidth((p * 200) + "px");
});
var second = allValues[1];
// ...
});
```
================================================
FILE: docs/docs/api/promise.all.md
================================================
---
layout: api
id: promise.all
title: Promise.all
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.all
```js
Promise.all(Iterable|Promise> input) -> Promise>
```
This method is useful for when you want to wait for more than one promise to complete.
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and return 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.
```js
var files = [];
for (var i = 0; i < 100; ++i) {
files.push(fs.writeFileAsync("file-" + i + ".txt", "", "utf-8"));
}
Promise.all(files).then(function() {
console.log("all the files were created");
});
```
This method is compatible with [`Promise.all`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) from native promises.
================================================
FILE: docs/docs/api/promise.any.md
================================================
---
layout: api
id: promise.any
title: Promise.any
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.any
```js
Promise.any(Iterable|Promise> input) -> Promise
```
Like [Promise.some](.), with 1 as `count`. However, if the promise fulfills, the fulfillment value is not an array of 1 but the value directly.
================================================
FILE: docs/docs/api/promise.bind.md
================================================
---
layout: api
id: promise.bind
title: Promise.bind
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.bind
```js
Promise.bind(
any|Promise thisArg,
[any|Promise value=undefined]
) -> BoundPromise
```
Create a promise that follows this promise or in the static method is resolved with the given `value`, but is bound to the given `thisArg` value. A bound promise will call its handlers with the bound value set to `this`. Additionally promises derived from a bound promise will also be bound promises with the same `thisArg` binding as the original promise.
If `thisArg` is a promise or thenable, its resolution will be awaited for and the bound value will be the promise's fulfillment value. If `thisArg` rejects
then the returned promise is rejected with the `thisArg's` rejection reason. Note that this means you cannot use `this` without checking inside catch handlers for promises that bind to promise because in case of rejection of `thisArg`, `this` will be `undefined`.
Without arrow functions that provide lexical `this`, the correspondence between async and sync code breaks down when writing object-oriented code. [`.bind`](.) alleviates this.
Consider:
```js
MyClass.prototype.method = function() {
try {
var contents = fs.readFileSync(this.file);
var url = urlParse(contents);
var result = this.httpGetSync(url);
var refined = this.refine(result);
return this.writeRefinedSync(refined);
}
catch (e) {
this.error(e.stack);
}
};
```
The above has a direct translation:
```js
MyClass.prototype.method = function() {
return fs.readFileAsync(this.file).bind(this)
.then(function(contents) {
var url = urlParse(contents);
return this.httpGetAsync(url);
}).then(function(result) {
var refined = this.refine(result);
return this.writeRefinedAsync(refined);
}).catch(function(e) {
this.error(e.stack);
});
};
```
`.bind` is the most efficient way of utilizing `this` with promises. The handler functions in the above code are not closures and can therefore even be hoisted out if needed. There is literally no overhead when propagating the bound value from one promise to another.
`.bind` also has a useful side purpose - promise handlers don't need to share a function to use shared state:
```js
somethingAsync().bind({})
.spread(function (aValue, bValue) {
this.aValue = aValue;
this.bValue = bValue;
return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
return this.aValue + this.bValue + cValue;
});
```
The above without [`.bind`](.) could be achieved with:
```js
var scope = {};
somethingAsync()
.spread(function (aValue, bValue) {
scope.aValue = aValue;
scope.bValue = bValue;
return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
return scope.aValue + scope.bValue + cValue;
});
```
However, there are many differences when you look closer:
- Requires a statement so cannot be used in an expression context
- If not there already, an additional wrapper function is required to undefined leaking or sharing `scope`
- The handler functions are now closures, thus less efficient and not reusable
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" `this`:
```js
something().bind(var1).then(function() {
//`this` is var1 here
return Promise.all(getStuff()).then(function(results) {
//`this` is undefined here
//refine results here etc
});
}).then(function() {
//`this` is var1 here
});
```
However, if you are utilizing the full bluebird API offering, you will *almost never* need to resort to nesting promises in the first place. The above should be written more like:
```js
something().bind(var1).then(function() {
//`this` is var1 here
return getStuff();
}).map(function(result) {
//`this` is var1 here
//refine result here
}).then(function() {
//`this` is var1 here
});
```
Also see this [Stackoverflow answer](http://stackoverflow.com/a/24412873/191693) as an additional example.
If you don't want to return a bound promise to the consumers of a promise, you can rebind the chain at the end:
```js
MyClass.prototype.method = function() {
return fs.readFileAsync(this.file).bind(this)
.then(function(contents) {
var url = urlParse(contents);
return this.httpGetAsync(url);
}).then(function(result) {
var refined = this.refine(result);
return this.writeRefinedAsync(refined);
}).catch(function(e) {
this.error(e.stack);
}).bind(); //The `thisArg` is implicitly undefined - I.E. the default promise `this` value
};
```
Rebinding can also be abused to do something gratuitous like this:
```js
Promise.resolve("my-element")
.bind(document)
.then(document.getElementById)
.bind(console)
.then(console.log);
```
The above does a `console.log` of `my-element`. Doing it this way is necessary because neither of the methods (`getElementById`, `console.log`) can be called as stand-alone methods.
================================================
FILE: docs/docs/api/promise.config.md
================================================
---
layout: api
id: promise.config
title: Promise.config
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.config
```js
Promise.config(Object {
warnings: boolean=false,
longStackTraces: boolean=false,
cancellation: boolean=false,
monitoring: boolean=false,
asyncHooks: boolean=false
} options) -> Object;
```
Configure long stack traces, warnings, monitoring, [async hooks](https://nodejs.org/api/async_hooks.html) and cancellation. Note that even though `false` is the default here, a development environment might be detected which automatically enables long stack traces and warnings. For **webpack** and **browserify** *development* environment is *always* enabled. See [installation](/docs/install.html#browserify-and-webpack) on how to configure webpack and browserify for production.
```js
Promise.config({
// Enable warnings
warnings: true,
// Enable long stack traces
longStackTraces: true,
// Enable cancellation
cancellation: true,
// Enable monitoring
monitoring: true,
// Enable async hooks
asyncHooks: true,
});
```
You can configure the warning for checking forgotten return statements with `wForgottenReturn`:
```js
Promise.config({
// Enables all warnings except forgotten return statements.
warnings: {
wForgottenReturn: false
}
});
```
`wForgottenReturn` is the only warning type that can be separately configured. The corresponding environmental variable key is `BLUEBIRD_W_FORGOTTEN_RETURN`.
In Node.js you may configure warnings and long stack traces for the entire process using environment variables:
```
BLUEBIRD_LONG_STACK_TRACES=1 BLUEBIRD_WARNINGS=1 node app.js
```
Both features are automatically enabled if the `BLUEBIRD_DEBUG` environment variable has been set or if the `NODE_ENV` environment variable is equal to `"development"`.
Using the value `0` will explicitly disable a feature despite debug environment otherwise activating it:
```
# Warnings are disabled despite being in development environment
NODE_ENV=development BLUEBIRD_WARNINGS=0 node app.js
```
Cancellation is always configured separately per bluebird instance.
# Async hooks
Bluebird supports [async hooks](https://nodejs.org/api/async_hooks.html) in node versions 9.6.0 and later. After it is enabled promises from the bluebird instance are assigned unique asyncIds:
```js
// Async hooks disabled for bluebird
const ah = require('async_hooks');
const Promise = require("bluebird");
Promise.resolve().then(() => {
console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
//
});
```
```js
// Async hooks enabled for bluebird
const ah = require('async_hooks');
const Promise = require("bluebird");
Promise.config({asyncHooks: true});
Promise.resolve().then(() => {
console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
//
});
```
================================================
FILE: docs/docs/api/promise.coroutine.addyieldhandler.md
================================================
---
layout: api
id: promise.coroutine.addyieldhandler
title: Promise.coroutine.addYieldHandler
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.coroutine.addYieldHandler
```js
Promise.coroutine.addYieldHandler(function handler) -> undefined
```
By default you can only yield Promises and Thenables inside coroutines. You can use this function to add yielding support for arbitrary types.
For example, if you wanted `yield 500` to be same as `yield Promise.delay`:
```js
Promise.coroutine.addYieldHandler(function(value) {
if (typeof value === "number") return Promise.delay(value);
});
```
Yield handlers are called when you yield something that is not supported by default. The first yield handler to return a promise or a thenable will be used.
If no yield handler returns a promise or a thenable then an error is raised.
An example of implementing callback support with `addYieldHandler`:
*This is a demonstration of how powerful the feature is and not the recommended usage. For best performance you need to use `promisifyAll` and yield promises directly.*
```js
var Promise = require("bluebird");
var fs = require("fs");
var _ = (function() {
var promise = null;
Promise.coroutine.addYieldHandler(function(v) {
if (v === undefined && promise != null) {
return promise;
}
promise = null;
});
return function() {
var def = Promise.defer();
promise = def.promise;
return def.callback;
};
})();
var readFileJSON = Promise.coroutine(function* (fileName) {
var contents = yield fs.readFile(fileName, "utf8", _());
return JSON.parse(contents);
});
```
An example of implementing thunks support with `addYieldHandler`:
*This is a demonstration of how powerful the feature is and not the recommended usage. For best performance you need to use `promisifyAll` and yield promises directly.*
```js
var Promise = require("bluebird");
var fs = require("fs");
Promise.coroutine.addYieldHandler(function(v) {
if (typeof v === "function") {
return Promise.fromCallback(function(cb) {
v(cb);
});
}
});
var readFileThunk = function(fileName, encoding) {
return function(cb) {
return fs.readFile(fileName, encoding, cb);
};
};
var readFileJSON = Promise.coroutine(function* (fileName) {
var contents = yield readFileThunk(fileName, "utf8");
return JSON.parse(contents);
});
```
An example of handling promises in parallel by adding an `addYieldHandler` for arrays :
```js
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
Promise.coroutine.addYieldHandler(function(yieldedValue) {
if (Array.isArray(yieldedValue)) return Promise.all(yieldedValue);
});
var readFiles = Promise.coroutine(function* (fileNames) {
return yield fileNames.map(function (fileName) {
return fs.readFileAsync(fileName, "utf8");
});
});
```
A custom yield handler can also be used just for a single call to `Promise.coroutine()`:
```js
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var readFiles = Promise.coroutine(function* (fileNames) {
return yield fileNames.map(function (fileName) {
return fs.readFileAsync(fileName, "utf8");
});
}, {
yieldHandler: function(yieldedValue) {
if (Array.isArray(yieldedValue)) return Promise.all(yieldedValue);
}
});
```
================================================
FILE: docs/docs/api/promise.coroutine.md
================================================
---
layout: api
id: promise.coroutine
title: Promise.coroutine
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.coroutine
```js
Promise.coroutine(GeneratorFunction(...arguments) generatorFunction, Object options) -> function
```
Returns a function that can use `yield` to yield promises. Control is returned back to the generator when the yielded promise settles. This can lead to less verbose code when doing lots of sequential async calls with minimal processing in between. Requires node.js 0.12+, io.js 1.0+ or Google Chrome 40+.
```js
var Promise = require("bluebird");
function PingPong() {
}
PingPong.prototype.ping = Promise.coroutine(function* (val) {
console.log("Ping?", val);
yield Promise.delay(500);
this.pong(val+1);
});
PingPong.prototype.pong = Promise.coroutine(function* (val) {
console.log("Pong!", val);
yield Promise.delay(500);
this.ping(val+1);
});
var a = new PingPong();
a.ping(0);
```
Running the example:
$ node test.js
Ping? 0
Pong! 1
Ping? 2
Pong! 3
Ping? 4
Pong! 5
Ping? 6
Pong! 7
Ping? 8
...
When called, the coroutine function will start an instance of the generator and returns a promise for its final value.
Doing `Promise.coroutine` is almost like using the C# `async` keyword to mark the function, with `yield` working as the `await` keyword. Promises are somewhat like `Task`s.
**Tip**
You are able to yield non-promise values by adding your own yield handler using [`Promise.coroutine.addYieldHandler`](.) or calling `Promise.coroutine()` with a yield handler function as `options.yieldHandler`.
================================================
FILE: docs/docs/api/promise.delay.md
================================================
---
layout: api
id: promise.delay
title: Promise.delay
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.delay
```js
Promise.delay(
int ms,
[any|Promise value=undefined]
) -> Promise
```
Returns a promise that will be resolved with `value` (or `undefined`) after given `ms` milliseconds. If `value` is a promise, the delay will start counting down when it is fulfilled and the returned promise will be fulfilled with the fulfillment value of the `value` promise. If `value` is a rejected promise, the resulting promise will be rejected immediately.
```js
Promise.delay(500).then(function() {
console.log("500 ms passed");
return "Hello world";
}).delay(500).then(function(helloWorldString) {
console.log(helloWorldString);
console.log("another 500 ms passed") ;
});
```
================================================
FILE: docs/docs/api/promise.each.md
================================================
---
layout: api
id: promise.each
title: Promise.each
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.each
```js
Promise.each(
Iterable|Promise> input,
function(any value, int index, int arrayLength) iterator
) -> Promise>
```
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) (an array, for example), or a promise of an `Iterable`, iterates serially over all the values in it, executing the given `iterator` on each element. If an element is a promise, the iterator will wait for it before proceeding. The `iterator` function has signature `(value, index, arrayLength)` where `value` is the current element (or its resolved value if it is a promise).
If, at any step:
* The iterator returns a promise or a thenable, it is awaited before continuing to the next iteration.
* The current element of the iteration is a *pending* promise, that promise will be awaited before running the iterator.
* The current element of the iteration is a *rejected* promise, the iteration will stop and be rejected as well (with the same reason).
If all iterations resolve successfully, the `Promise.each` call resolves to a new array containing the resolved values of the original input elements.
`Promise.each` is very similar to [Promise.mapSeries](.). The difference between `Promise.each` and `Promise.mapSeries` is their resolution value. `Promise.each` resolves with an array as explained above, while `Promise.mapSeries` resolves with an array containing the *outputs* of the iterator function on each step. This way, `Promise.each` is meant to be mainly used for side-effect operations (since the outputs of the iterator are essentially discarded), just like the native `.forEach()` method of arrays, while `Promise.map` is meant to be used as an async version of the native `.map()` method of arrays.
Basic example:
```js
// The array to be iterated over can be a mix of values and promises.
var fileNames = ["1.txt", Promise.resolve("2.txt"), "3.txt", Promise.delay(3000, "4.txt"), "5.txt"];
Promise.each(fileNames, function(fileName, index, arrayLength) {
// The iteration will be performed sequentially, awaiting for any
// promises in the process.
return fs.readFileAsync(fileName).then(function(fileContents) {
// ...
// The final resolution value of the iterator is is irrelevant,
// since the result of the `Promise.each` has nothing to do with
// the outputs of the iterator.
return "anything"; // Doesn't matter
});
}).then(function(result) {
// This will run after the last step is done
console.log("Done!")
console.log(result); // ["1.txt", "2.txt", "3.txt", "4.txt", "5.txt"]
});
```
##Example
```js
let stories = [ '8952', '8884'];
Promise.each(stories, (item, idx, length) => {
return request.getAsync(`https://hacker-news.firebaseio.com/v0/item/${item}.json?print=pretty`)
.then(res => {
// need to do explicit operations here
})
})
.then(result => {
console.log('ALL done', result);//['8952', '8884']
})
```
[api/promise.each](unfinished-article)
=======
Example with a rejected promise in the array:
```js
// If one of the promises in the original array rejects,
// the iteration will stop once it reaches it
var items = ["A", Promise.delay(8000, "B"), Promise.reject("C"), "D"];
Promise.each(items, function(item) {
return Promise.delay(4000).then(function() {
console.log("On iterator: " + item);
});
}).then(function(result) {
// This not run
}).catch(function(rejection) {
console.log("Catch: " + rejection);
});
// The code above outputs the following after 12 seconds (not 16!):
// On iterator: A
// On iterator: B
// Catch: C
```
================================================
FILE: docs/docs/api/promise.filter.md
================================================
---
layout: api
id: promise.filter
title: Promise.filter
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.filter
```js
Promise.filter(
Iterable|Promise> input,
function(any item, int index, int length) filterer,
[Object {concurrency: int=Infinity} options]
) -> Promise
```
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and [filter the array to another](http://en.wikipedia.org/wiki/Filter_\(higher-order_function\)) using the given `filterer` function.
It is essentially an efficient shortcut for doing a [.map](.) and then [`Array#filter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter):
```js
Promise.map(valuesToBeFiltered, function(value, index, length) {
return Promise.all([filterer(value, index, length), value]);
}).then(function(values) {
return values.filter(function(stuff) {
return stuff[0] == true
}).map(function(stuff) {
return stuff[1];
});
});
```
Example for filtering files that are accessible directories in the current directory:
```js
var Promise = require("bluebird");
var E = require("core-error-predicates");
var fs = Promise.promisifyAll(require("fs"));
fs.readdirAsync(process.cwd()).filter(function(fileName) {
return fs.statAsync(fileName)
.then(function(stat) {
return stat.isDirectory();
})
.catch(E.FileAccessError, function() {
return false;
});
}).each(function(directoryName) {
console.log(directoryName, " is an accessible directory");
});
```
####Filter Option: concurrency
See [Map Option: concurrency](#map-option-concurrency)
================================================
FILE: docs/docs/api/promise.fromcallback.md
================================================
---
layout: api
id: promise.fromcallback
title: Promise.fromCallback
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.fromCallback
```js
Promise.fromCallback(
function(function callback) resolver,
[Object {multiArgs: boolean=false} options]
) -> Promise
```
```js
Promise.fromNode(
function(function callback) resolver,
[Object {multiArgs: boolean=false} options]
) -> Promise
```
Returns a promise that is resolved by a node style callback function. This is the most fitting way to do on the fly promisification when libraries don't expose classes for automatic promisification by undefined.
The resolver function is passed a callback that expects to be called back according to error-first node conventions.
Setting `multiArgs` to `true` means the resulting promise will always fulfill with an array of the callback's success value(s). This is needed because promises only support a single success value while
some callback API's have multiple success value. The default is to ignore all but the first success value of a callback function.
Using manual resolver:
```js
var Promise = require("bluebird");
// "email-templates" doesn't expose prototypes for promisification
var emailTemplates = Promise.promisify(require('email-templates'));
var templatesDir = path.join(__dirname, 'templates');
emailTemplates(templatesDir).then(function(template) {
return Promise.fromCallback(function(callback) {
return template("newsletter", callback);
}, {multiArgs: true}).spread(function(html, text) {
console.log(html, text);
});
});
```
The same can also be written more concisely with `Function.prototype.bind`:
```js
var Promise = require("bluebird");
// "email-templates" doesn't expose prototypes for promisification
var emailTemplates = Promise.promisify(require('email-templates'));
var templatesDir = path.join(__dirname, 'templates');
emailTemplates(templatesDir).then(function(template) {
return Promise.fromCallback(template.bind(null, "newsletter"), {multiArgs: true})
.spread(function(html, text) {
console.log(html, text);
});
});
```
================================================
FILE: docs/docs/api/promise.getnewlibrarycopy.md
================================================
---
layout: api
id: promise.getnewlibrarycopy
title: Promise.getNewLibraryCopy
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.getNewLibraryCopy
```js
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.
A basic example:
```js
var Promise = require('bluebird');
var Promise2 = Promise.getNewLibraryCopy();
Promise2.x = 123;
console.log(Promise2 == Promise); // false
console.log(Promise2.x); // 123
console.log(Promise.x); // undefined
```
`Promise2` is independent to `Promise`. Any changes to `Promise2` do not affect the copy of Bluebird returned by `require('bluebird')`.
In practice:
```js
var Promise = require('bluebird').getNewLibraryCopy();
Promise.coroutine.addYieldHandler( function() { /* */ } ); // alters behavior of `Promise.coroutine()`
// somewhere in another file or module in same app
var Promise = require('bluebird');
Promise.coroutine(function*() {
// this code is unaffected by the yieldHandler defined above
// because it was defined on an independent copy of Bluebird
});
```
================================================
FILE: docs/docs/api/promise.join.md
================================================
---
layout: api
id: promise.join
title: Promise.join
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.join
```js
Promise.join(
Promise|any values...,
function handler
) -> Promise
```
For coordinating multiple concurrent discrete promises. 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 discrete promises that you want to coordinate concurrently. The final parameter, handler function, will be invoked with the result values of all of the fulfilled promises. For example:
```js
var Promise = require("bluebird");
var join = Promise.join;
join(getPictures(), getComments(), getTweets(),
function(pictures, comments, tweets) {
console.log("in total: " + pictures.length + comments.length + tweets.length);
});
```
```js
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var pg = require("pg");
Promise.promisifyAll(pg, {
filter: function(methodName) {
return methodName === "connect"
},
multiArgs: true
});
// Promisify rest of pg normally
Promise.promisifyAll(pg);
var join = Promise.join;
var connectionString = "postgres://username:password@localhost/database";
var fContents = fs.readFileAsync("file.txt", "utf8");
var fStat = fs.statAsync("file.txt");
var fSqlClient = pg.connectAsync(connectionString).spread(function(client, done) {
client.close = done;
return client;
});
join(fContents, fStat, fSqlClient, function(contents, stat, sqlClient) {
var query = " \
INSERT INTO files (byteSize, contents) \
VALUES ($1, $2) \
";
return sqlClient.queryAsync(query, [stat.size, contents]).thenReturn(query);
})
.then(function(query) {
console.log("Successfully ran the Query: " + query);
})
.finally(function() {
// This is why you want to use Promise.using for resource management
if (fSqlClient.isFulfilled()) {
fSqlClient.value().close();
}
});
```
*Note: In 1.x and 0.x `Promise.join` used to be a `Promise.all` that took the values in as arguments instead of an array. This behavior has been deprecated but is still supported partially - when the last argument is an immediate function value the new semantics will apply*
================================================
FILE: docs/docs/api/promise.longstacktraces.md
================================================
---
layout: api
id: promise.longstacktraces
title: Promise.longStackTraces
---
[← Back To API Reference](/docs/api-reference.html)
## ~~Promise.longStackTraces~~
This method is deprecated. Use [Promise.config](/docs/api/promise.config.html) instead.
```js
Promise.config({
longStackTraces: true
})
```
---
```js
Promise.longStackTraces() -> undefined
```
Call this right after the library is loaded to enable long stack traces. Long stack traces cannot be disabled after being enabled, and cannot be enabled after promises have already been created. Long stack traces imply a substantial performance penalty, around 4-5x for throughput and 0.5x for latency.
Long stack traces are enabled by default in the debug build.
To enable them in all instances of bluebird in node.js, use the environment variable `BLUEBIRD_DEBUG`:
```
BLUEBIRD_DEBUG=1 node server.js
```
Setting the environment variable `NODE_ENV` to `"development"` also automatically enables long stack traces.
You should enabled long stack traces if you want better debugging experience. For example:
```js
Promise.longStackTraces();
Promise.resolve().then(function outer() {
return Promise.resolve().then(function inner() {
return Promise.resolve().then(function evenMoreInner() {
a.b.c.d()
}).catch(function catcher(e) {
console.error(e.stack);
});
});
});
```
Gives
ReferenceError: a is not defined
at evenMoreInner (:6:13)
From previous event:
at inner (:5:24)
From previous event:
at outer (:4:20)
From previous event:
at :3:9
at Object.InjectedScript._evaluateOn (:581:39)
at Object.InjectedScript._evaluateAndWrap (:540:52)
at Object.InjectedScript.evaluate (:459:21)
While with long stack traces disabled, you would get:
ReferenceError: a is not defined
at evenMoreInner (:6:13)
at tryCatch1 (:41:19)
at Promise$_resolvePromise [as _resolvePromise] (:1739:13)
at Promise$_resolveLast [as _resolveLast] (:1520:14)
at Async$_consumeFunctionBuffer [as _consumeFunctionBuffer] (:560:33)
at Async$consumeFunctionBuffer (:515:14)
at MutationObserver.Promise$_Deferred (:433:17)
On client side, long stack traces currently only work in recent Firefoxes, Chrome and Internet Explorer 10+.
================================================
FILE: docs/docs/api/promise.map.md
================================================
---
layout: api
id: promise.map
title: Promise.map
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.map
```js
Promise.map(
Iterable|Promise> input,
function(any item, int index, int length) mapper,
[Object {concurrency: int=Infinity} options]
) -> Promise
```
Given a finite [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and [map the array to another](http://en.wikipedia.org/wiki/Map_\(higher-order_function\)) using the given `mapper` function.
Promises returned by the `mapper` function are awaited for and the returned promise doesn't fulfill until all mapped promises have fulfilled as well. 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, that is, 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`.
A common use of `Promise.map` is to replace the `.push`+`Promise.all` boilerplate:
```js
var promises = [];
for (var i = 0; i < fileNames.length; ++i) {
promises.push(fs.readFileAsync(fileNames[i]));
}
Promise.all(promises).then(function() {
console.log("done");
});
// Using Promise.map:
Promise.map(fileNames, function(fileName) {
// Promise.map awaits for returned promises as well.
return fs.readFileAsync(fileName);
}).then(function() {
console.log("done");
});
// Using Promise.map and async/await:
await Promise.map(fileNames, function(fileName) {
// Promise.map awaits for returned promises as well.
return fs.readFileAsync(fileName);
});
console.log("done");
```
A more involved example:
```js
var Promise = require("bluebird");
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
fs.readdirAsync(".").map(function(fileName) {
var stat = fs.statAsync(fileName);
var contents = fs.readFileAsync(fileName).catch(function ignore() {});
return join(stat, contents, function(stat, contents) {
return {
stat: stat,
fileName: fileName,
contents: contents
}
});
// The return value of .map is a promise that is fulfilled with an array of the mapped values
// That means we only get here after all the files have been statted and their contents read
// into memory. If you need to do more operations per file, they should be chained in the map
// callback for concurrency.
}).call("sort", function(a, b) {
return a.fileName.localeCompare(b.fileName);
}).each(function(file) {
var contentLength = file.stat.isDirectory() ? "(directory)" : file.contents.length + " bytes";
console.log(file.fileName + " last modified " + file.stat.mtime + " " + contentLength)
});
```
####Map Option: concurrency
You may optionally specify a concurrency limit:
```js
...map(..., {concurrency: 3});
```
The concurrency limit applies to Promises returned by the mapper function and it basically limits the number of Promises created. For example, if `concurrency` is `3` and the mapper callback has been called enough so that there are three returned Promises currently pending, no further callbacks are called until one of the pending Promises resolves. So the mapper function will be called three times and it will be called again only after at least one of the Promises resolves.
Playing with the first example with and without limits, and seeing how it affects the duration when reading 20 files:
```js
var Promise = require("bluebird");
var join = Promise.join;
var fs = Promise.promisifyAll(require("fs"));
var concurrency = parseFloat(process.argv[2] || "Infinity");
console.time("reading files");
fs.readdirAsync(".").map(function(fileName) {
var stat = fs.statAsync(fileName);
var contents = fs.readFileAsync(fileName).catch(function ignore() {});
return join(stat, contents, function(stat, contents) {
return {
stat: stat,
fileName: fileName,
contents: contents
}
});
// The return value of .map is a promise that is fulfilled with an array of the mapped values
// That means we only get here after all the files have been statted and their contents read
// into memory. If you need to do more operations per file, they should be chained in the map
// callback for concurrency.
}, {concurrency: concurrency}).call("sort", function(a, b) {
return a.fileName.localeCompare(b.fileName);
}).then(function() {
console.timeEnd("reading files");
});
```
```bash
$ sync && echo 3 > /proc/sys/vm/drop_caches
$ node test.js 1
reading files 35ms
$ sync && echo 3 > /proc/sys/vm/drop_caches
$ node test.js Infinity
reading files: 9ms
```
The order `map` calls the mapper function on the array elements is not specified, there is no guarantee on the order in which it'll execute the `map`er on the elements. For order guarantee in sequential execution - see [Promise.mapSeries](.).
================================================
FILE: docs/docs/api/promise.mapseries.md
================================================
---
layout: api
id: promise.mapseries
title: Promise.mapSeries
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.mapSeries
```js
Promise.mapSeries(
Iterable|Promise> input,
function(any value, int index, int arrayLength) mapper
) -> Promise>
```
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) (an array, for example), or a promise of an `Iterable`, iterates serially over all the values in it, executing the given `mapper` on each element. If an element is a promise, the mapper will wait for it before proceeding. The `mapper` function has signature `(value, index, arrayLength)` where `value` is the current element (or its resolved value if it is a promise).
If, at any step:
* The mapper returns a promise or a thenable, it is awaited before continuing to the next iteration.
* The current element of the iteration is a *pending* promise, that promise will be awaited before running the mapper.
* The current element of the iteration is a *rejected* promise, the iteration will stop and be rejected as well (with the same reason).
If all iterations resolve successfully, the `Promise.mapSeries` call resolves to a new array containing the results of each `mapper` execution, in order.
`Promise.mapSeries` is very similar to [Promise.each](.). The difference between `Promise.each` and `Promise.mapSeries` is their resolution value. `Promise.mapSeries` resolves with an array as explained above, while `Promise.each` resolves with an array containing the *resolved values of the input elements* (ignoring the outputs of the iteration steps). This way, `Promise.each` is meant to be mainly used for side-effect operations (since the outputs of the iterator are essentially discarded), just like the native `.forEach()` method of arrays, while `Promise.map` is meant to be used as an async version of the native `.map()` method of arrays.
Basic example:
```js
// The array to be mapped over can be a mix of values and promises.
var fileNames = ["1.txt", Promise.resolve("2.txt"), "3.txt", Promise.delay(3000, "4.txt"), "5.txt"];
Promise.mapSeries(fileNames, function(fileName, index, arrayLength) {
// The iteration will be performed sequentially, awaiting for any
// promises in the process.
return fs.readFileAsync(fileName).then(function(fileContents) {
// ...
return fileName + "!";
});
}).then(function(result) {
// This will run after the last step is done
console.log("Done!")
console.log(result); // ["1.txt!", "2.txt!", "3.txt!", "4.txt!", "5.txt!"]
});
```
Example with a rejected promise in the array:
```js
// If one of the promises in the original array rejects,
// the iteration will stop once it reaches it
var items = ["A", Promise.delay(8000, "B"), Promise.reject("C"), "D"];
Promise.each(items, function(item) {
return Promise.delay(4000).then(function() {
console.log("On mapper: " + item);
});
}).then(function(result) {
// This not run
}).catch(function(rejection) {
console.log("Catch: " + rejection);
});
// The code above outputs the following after 12 seconds (not 16!):
// On mapper: A
// On mapper: B
// Catch: C
```
================================================
FILE: docs/docs/api/promise.method.md
================================================
---
layout: api
id: promise.method
title: Promise.method
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.method
```js
Promise.method(function(...arguments) fn) -> function
```
Returns a new function that wraps the given function `fn`. 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.
This method is convenient when a function can sometimes return synchronously or throw synchronously.
Example without using `Promise.method`:
```js
MyClass.prototype.method = function(input) {
if (!this.isValid(input)) {
return Promise.reject(new TypeError("input is not valid"));
}
if (this.cache(input)) {
return Promise.resolve(this.someCachedValue);
}
return db.queryAsync(input).bind(this).then(function(value) {
this.someCachedValue = value;
return value;
});
};
```
Using the same function `Promise.method`, there is no need to manually wrap direct return or throw values into a promise:
```js
MyClass.prototype.method = Promise.method(function(input) {
if (!this.isValid(input)) {
throw new TypeError("input is not valid");
}
if (this.cache(input)) {
return this.someCachedValue;
}
return db.queryAsync(input).bind(this).then(function(value) {
this.someCachedValue = value;
return value;
});
});
```
================================================
FILE: docs/docs/api/promise.noconflict.md
================================================
---
layout: api
id: promise.noconflict
title: Promise.noConflict
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.noConflict
```js
Promise.noConflict() -> Object
```
This is relevant to browser environments with no module loader.
Release control of the `Promise` namespace to whatever it was before this library was loaded. Returns a reference to the library namespace so you can attach it to something else.
```html
```
================================================
FILE: docs/docs/api/promise.onpossiblyunhandledrejection.md
================================================
---
layout: api
id: promise.onpossiblyunhandledrejection
title: Promise.onPossiblyUnhandledRejection
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.onPossiblyUnhandledRejection
```js
Promise.onPossiblyUnhandledRejection(function(any error, Promise promise) handler) -> undefined
```
*Note: this hook is specific to the bluebird instance it's called on, application developers should use [global rejection events](/docs/api/error-management-configuration.html#global-rejection-events)*
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.
```js
Promise.onPossiblyUnhandledRejection(function(e, promise) {
throw e;
});
```
Passing no value or a non-function will have the effect of removing any kind of handling for possibly unhandled rejections.
================================================
FILE: docs/docs/api/promise.onunhandledrejectionhandled.md
================================================
---
layout: api
id: promise.onunhandledrejectionhandled
title: Promise.onUnhandledRejectionHandled
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.onUnhandledRejectionHandled
```js
Promise.onUnhandledRejectionHandled(function(Promise promise) handler) -> undefined
```
*Note: this hook is specific to the bluebird instance its called on, application developers should use [global rejection events](/docs/api/error-management-configuration.html#global-rejection-events)*
Add `handler` as the handler to call when a rejected promise that was reported as "possibly unhandled rejection" became handled.
Together with `onPossiblyUnhandledRejection` these hooks can be used to implement a debugger that will show a list
of unhandled promise rejections updated in real time as promises become handled.
For example:
```js
var unhandledPromises = [];
Promise.onPossiblyUnhandledRejection(function(reason, promise) {
unhandledPromises.push(promise);
//Update some debugger UI
});
Promise.onUnhandledRejectionHandled(function(promise) {
var index = unhandledPromises.indexOf(promise);
unhandledPromises.splice(index, 1);
//Update the debugger UI
});
```
================================================
FILE: docs/docs/api/promise.promisify.md
================================================
---
layout: api
id: promise.promisify
title: Promise.promisify
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.promisify
```js
Promise.promisify(
function(any arguments..., function callback) nodeFunction,
[Object {
multiArgs: boolean=false,
context: any=this
} options]
) -> function
```
Returns a function that will wrap the given `nodeFunction`. Instead of taking a callback, the returned function will return a promise whose fate is decided by the callback behavior of the given node function. The node function should conform to node.js convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument.
If the `nodeFunction` calls its callback with multiple success values, the fulfillment value will be the first fulfillment item.
Setting `multiArgs` to `true` means the resulting promise will always fulfill with an array of the callback's success value(s). This is needed because promises only support a single success value while some callback API's have multiple success value. The default is to ignore all but the first success value of a callback function.
If you pass a `context`, the `nodeFunction` will be called as a method on the `context`.
Example of promisifying the asynchronous `readFile` of node.js `fs`-module:
```js
var readFile = Promise.promisify(require("fs").readFile);
readFile("myfile.js", "utf8").then(function(contents) {
return eval(contents);
}).then(function(result) {
console.log("The result of evaluating myfile.js", result);
}).catch(SyntaxError, function(e) {
console.log("File had syntax error", e);
//Catch any other error
}).catch(function(e) {
console.log("Error reading file", e);
});
```
Note that if the node function is a method of some object, you can pass the object as the second argument like so:
```js
var redisGet = Promise.promisify(redisClient.get, {context: redisClient});
redisGet('foo').then(function() {
//...
});
```
But this will also work:
```js
var getAsync = Promise.promisify(redisClient.get);
getAsync.call(redisClient, 'foo').then(function() {
//...
});
```
================================================
FILE: docs/docs/api/promise.promisifyall.md
================================================
---
layout: api
id: promise.promisifyall
title: Promise.promisifyAll
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.promisifyAll
```js
Promise.promisifyAll(
Object target,
[Object {
suffix: String="Async",
multiArgs: boolean=false,
filter: boolean function(String name, function func, Object target, boolean passesDefaultFilter),
promisifier: function(function originalFunction, function defaultPromisifier)
} options]
) -> Object
```
Promisifies the entire object by going through the object's properties and creating an async equivalent of each function on the object and its prototype chain. The promisified method name will be the original method name suffixed with `suffix` (default is `"Async"`). Any class properties of the object (which is the case for the main export of many modules) are also promisified, both static and instance methods. Class property is a property with a function value that has a non-empty `.prototype` object. Returns the input object.
Note that the original methods on the object are not overwritten but new methods are created with the `Async`-suffix. For example, if you `promisifyAll` the node.js `fs` object use `fs.statAsync` to call the promisified `stat` method.
Example:
```js
Promise.promisifyAll(require("redis"));
//Later on, all redis client instances have promise returning functions:
redisClient.hexistsAsync("myhash", "field").then(function(v) {
}).catch(function(e) {
});
```
It also works on singletons or specific instances:
```js
var fs = Promise.promisifyAll(require("fs"));
fs.readFileAsync("myfile.js", "utf8").then(function(contents) {
console.log(contents);
}).catch(function(e) {
console.error(e.stack);
});
```
See [promisification](#promisification) for more examples.
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. The target methods are assumed to conform to node.js callback convention of accepting a callback as last argument and calling that callback with error as the first argument and success value on the second argument. If the node method calls its callback with multiple success values, the fulfillment value will be an array of them.
If a method name already has an `"Async"`-suffix, an exception will be thrown.
####Option: suffix
Optionally, you can define a custom suffix through the options object:
```js
var fs = Promise.promisifyAll(require("fs"), {suffix: "MySuffix"});
fs.readFileMySuffix(...).then(...);
```
All the above limitations apply to custom suffices:
- Choose the suffix carefully, it must not collide with anything
- PascalCase the suffix
- The suffix must be a valid JavaScript identifier using ASCII letters
- Always use the same suffix everywhere in your application, you could create a wrapper to make this easier:
```js
module.exports = function myPromisifyAll(target) {
return Promise.promisifyAll(target, {suffix: "MySuffix"});
};
```
####Option: multiArgs
Setting `multiArgs` to `true` means the resulting promise will always fulfill with an array of the callback's success value(s). This is needed because promises only support a single success value while some callback API's have multiple success value. The default is to ignore all but the first success value of a callback function.
If a module has multiple argument callbacks as an exception rather than the rule, you can filter out the multiple argument methods in first go and then promisify rest of the module in second go:
```js
Promise.promisifyAll(something, {
filter: function(name) {
return name === "theMultiArgMethodIwant";
},
multiArgs: true
});
// Rest of the methods
Promise.promisifyAll(something);
```
####Option: filter
Optionally, you can define a custom filter through the options object:
```js
Promise.promisifyAll(..., {
filter: function(name, func, target, passesDefaultFilter) {
// name = the property name to be promisified without suffix
// func = the function
// target = the target object where the promisified func will be put with name + suffix
// passesDefaultFilter = whether the default filter would be passed
// return boolean (return value is coerced, so not returning anything is same as returning false)
return passesDefaultFilter && ...
}
})
```
The default filter function will ignore properties that start with a leading underscore, properties that are not valid JavaScript identifiers and constructor functions (function which have enumerable properties in their `.prototype`).
####Option: promisifier
Optionally, you can define a custom promisifier, so you could promisifyAll e.g. the chrome APIs used in Chrome extensions.
The promisifier gets a reference to the original method and should return a function which returns a promise.
```js
function DOMPromisifier(originalMethod) {
// return a function
return function promisified() {
var args = [].slice.call(arguments);
// Needed so that the original method can be called with the correct receiver
var self = this;
// which returns a promise
return new Promise(function(resolve, reject) {
args.push(resolve, reject);
originalMethod.apply(self, args);
});
};
}
// Promisify e.g. chrome.browserAction
Promise.promisifyAll(chrome.browserAction, {promisifier: DOMPromisifier});
// Later
chrome.browserAction.getTitleAsync({tabId: 1})
.then(function(result) {
});
```
Combining `filter` with `promisifier` for the restler module to promisify event emitter:
```js
var Promise = require("bluebird");
var restler = require("restler");
var methodNamesToPromisify = "get post put del head patch json postJson putJson".split(" ");
function EventEmitterPromisifier(originalMethod) {
// return a function
return function promisified() {
var args = [].slice.call(arguments);
// Needed so that the original method can be called with the correct receiver
var self = this;
// which returns a promise
return new Promise(function(resolve, reject) {
// We call the originalMethod here because if it throws,
// it will reject the returned promise with the thrown error
var emitter = originalMethod.apply(self, args);
emitter
.on("success", function(data, response) {
resolve([data, response]);
})
.on("fail", function(data, response) {
// Erroneous response like 400
resolve([data, response]);
})
.on("error", function(err) {
reject(err);
})
.on("abort", function() {
reject(new Promise.CancellationError());
})
.on("timeout", function() {
reject(new Promise.TimeoutError());
});
});
};
};
Promise.promisifyAll(restler, {
filter: function(name) {
return methodNamesToPromisify.indexOf(name) > -1;
},
promisifier: EventEmitterPromisifier
});
// ...
// Later in some other file
var restler = require("restler");
restler.getAsync("http://...", ...,).spread(function(data, response) {
})
```
Using `defaultPromisifier` parameter to add enhancements on top of normal node
promisification:
```js
var fs = Promise.promisifyAll(require("fs"), {
promisifier: function(originalFunction, defaultPromisifer) {
var promisified = defaultPromisifier(originalFunction);
return function() {
// Enhance normal promisification by supporting promises as
// arguments
var args = [].slice.call(arguments);
var self = this;
return Promise.all(args).then(function(awaitedArgs) {
return promisified.apply(self, awaitedArgs);
});
};
}
});
// All promisified fs functions now await their arguments if they are promises
var version = fs.readFileAsync("package.json", "utf8").then(JSON.parse).get("version");
fs.writeFileAsync("the-version.txt", version, "utf8");
```
####Promisifying multiple classes in one go
You can promisify multiple classes in one go by constructing an array out of the classes and passing it to `promisifyAll`:
```js
var Pool = require("mysql/lib/Pool");
var Connection = require("mysql/lib/Connection");
Promise.promisifyAll([Pool, Connection]);
```
This works because the array acts as a "module" where the indices are the "module"'s properties for classes.
================================================
FILE: docs/docs/api/promise.props.md
================================================
---
layout: api
id: promise.props
title: Promise.props
---
[← Back To API Reference](/docs/api-reference.html)
================================================
FILE: docs/docs/api/promise.race.md
================================================
---
layout: api
id: promise.race
title: Promise.race
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.race
```js
Promise.race(Iterable|Promise> input) -> Promise
```
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and 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.
This method is only implemented because it's in the ES6 standard. If you want to race promises to fulfillment the [`.any`](.) method is more appropriate as it doesn't qualify a rejected promise as the winner. It also has less surprises: `.race` must become infinitely pending if an empty array is passed but passing an empty array to [`.any`](.) is more usefully a `RangeError`
================================================
FILE: docs/docs/api/promise.reduce.md
================================================
---
layout: api
id: promise.reduce
title: Promise.reduce
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.reduce
```js
Promise.reduce(
Iterable|Promise> input,
function(any accumulator, any item, int index, int length) reducer,
[any initialValue]
) -> Promise
```
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and [reduce the array to a value](http://en.wikipedia.org/wiki/Fold_\(higher-order_function\)) using the given `reducer` function.
If the reducer function returns a promise, then the result of the promise is awaited, before continuing with next iteration. If any promise in the array is rejected or a promise returned by the reducer function is rejected, the result is rejected as well.
Read given files sequentially while summing their contents as an integer. Each file contains just the text `10`.
```js
Promise.reduce(["file1.txt", "file2.txt", "file3.txt"], function(total, fileName) {
return fs.readFileAsync(fileName, "utf8").then(function(contents) {
return total + parseInt(contents, 10);
});
}, 0).then(function(total) {
//Total is 30
});
```
*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` (which awaits for the entire array before you can call [`Array#reduce`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) on it).
================================================
FILE: docs/docs/api/promise.reject.md
================================================
---
layout: api
id: promise.reject
title: Promise.reject
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.reject
```js
Promise.reject(any error) -> Promise
```
Create a promise that is rejected with the given `error`.
================================================
FILE: docs/docs/api/promise.resolve.md
================================================
---
layout: api
id: promise.resolve
title: Promise.resolve
---
[← Back To API Reference](/docs/api-reference.html)
## Promise.resolve
```js
Promise.resolve(Promise|any 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 not a thenable, a fulfilled Promise is returned with `value` as its fulfillment value. 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.
This can be useful if a function returns a promise (say into a chain) but can optionally return a static value. Say, for a lazy-loaded value. Example:
```js
var someCachedValue;
var getValue = function() {
if (someCachedValue) {
return Promise.resolve(someCachedValue);
}
return db.queryAsync().then(function(value) {
someCachedValue = value;
return value;
});
};
```
Another example with handling jQuery castable objects (`$` is jQuery)
```js
Promise.resolve($.get("http://www.google.com")).then(function() {
//Returning a thenable from a handler is automatically
//cast to a trusted Promise as per Promises/A+ specification
return $.post("http://www.yahoo.com");
}).then(function() {
}).catch(function(e) {
//jQuery doesn't throw real errors so use catch-all
console.log(e.statusText);
});
```
================================================
FILE: docs/docs/api/promise.setscheduler.md
================================================
---
layout: api
id: promise.setscheduler
title: Promise.setScheduler
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.setScheduler
```js
Promise.setScheduler(function(function fn) scheduler) -> function
```
Scheduler should be a function that asynchronously schedules the calling of the passed in function:
```js
// This is just an example of how to use the api, there is no reason to do this
Promise.setScheduler(function(fn) {
setTimeout(fn, 0);
});
```
Setting a custom scheduler could be necessary when you need a faster way to schedule functions than bluebird does by default. It also makes bluebird possible to use in platforms where normal timing constructs like `setTimeout` and `process.nextTick` are not available (like Nashhorn).
You can also use it as a hook:
```js
// This will synchronize bluebird promise queue flushing with angulars queue flushing
// Angular is also now responsible for choosing the actual scheduler
Promise.setScheduler(function(fn) {
$rootScope.$evalAsync(fn);
});
```
> **Danger** - in order to keep bluebird promises [Promises/A+](https://promisesaplus.com/) compliant a scheduler that executes the function asynchronously (like the examples in this page) must be used.
================================================
FILE: docs/docs/api/promise.some.md
================================================
---
layout: api
id: promise.some
title: Promise.some
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.some
```js
Promise.some(
Iterable|Promise> input,
int count
) -> Promise
```
Given an [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols)\(arrays are `Iterable`\), or a promise of an `Iterable`, which produces promises (or a mix of promises and values), iterate over all the values in the `Iterable` into an array and return a promise that is fulfilled as soon as `count` promises are fulfilled in the array. The fulfillment value is an array with `count` values in the order they were fulfilled.
This example pings 4 nameservers, and logs the fastest 2 on console:
```js
Promise.some([
ping("ns1.example.com"),
ping("ns2.example.com"),
ping("ns3.example.com"),
ping("ns4.example.com")
], 2).spread(function(first, second) {
console.log(first, second);
});
```
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 in.
You can get a reference to [AggregateError](.) from `Promise.AggregateError`.
```js
Promise.some(...)
.then(...)
.then(...)
.catch(Promise.AggregateError, function(err) {
err.forEach(function(e) {
console.error(e.stack);
});
});
```
================================================
FILE: docs/docs/api/promise.try.md
================================================
---
layout: api
id: promise.try
title: Promise.try
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.try
```js
Promise.try(function() fn) -> Promise
```
```js
Promise.attempt(function() fn) -> Promise
```
Start the chain of promises with `Promise.try`. Any synchronous exceptions will be turned into rejections on the returned promise.
```js
function getUserById(id) {
return Promise.try(function() {
if (typeof id !== "number") {
throw new Error("id must be a number");
}
return db.getUserById(id);
});
}
```
Now if someone uses this function, they will catch all errors in their Promise `.catch` handlers instead of having to handle both synchronous and asynchronous exception flows.
*For compatibility with earlier ECMAScript version, an alias `Promise.attempt` is provided for [`Promise.try`](.).*
================================================
FILE: docs/docs/api/promise.using.md
================================================
---
layout: api
id: promise.using
title: Promise.using
---
[← Back To API Reference](/docs/api-reference.html)
##Promise.using
```js
Promise.using(
Promise|Disposer|any resource,
Promise|Disposer|any resource...,
function(any resources...) handler
) -> Promise
```
```js
Promise.using(
Array resources,
function(Array resources) handler
) -> Promise
```
In conjunction with [`.disposer`](.), `using` will make sure that no matter what, the specified disposer will be called when the promise returned by the callback passed to `using` has settled. The disposer is necessary because there is no standard interface in node for disposing resources.
Here is a simple example (where `getConnection()` has been defined to return a proper Disposer object)
```js
using(getConnection(), function(connection) {
// Don't leak the `connection` variable anywhere from here
// it is only guaranteed to be open while the promise returned from
// this callback is still pending
return connection.queryAsync("SELECT * FROM TABLE");
// Code that is chained from the promise created in the line above
// still has access to `connection`
}).then(function(rows) {
// The connection has been closed by now
console.log(rows);
});
```
Using multiple resources:
```js
using(getConnection(), function(conn1) {
return using(getConnection(), function(conn2) {
// use conn1 and conn 2 here
});
}).then(function() {
// Both connections closed by now
})
```
The above can also be written as (with a caveat, see below)
```js
using(getConnection(), getConnection(), function(conn1, conn2) {
// use conn1 and conn2
}).then(function() {
// Both connections closed by now
})
```
However, if the second `getConnection` throws **synchronously**, the first connection is leaked. This will not happen
when using APIs through bluebird promisified methods though. You can wrap functions that could throw in [`Promise.method`](.) which will turn synchronous rejections into rejected promises.
Note that you can mix promises and disposers, so that you can acquire all the things you need in parallel instead of sequentially
```js
// The files don't need resource management but you should
// still start the process of reading them even before you have the connection
// instead of waiting for the connection
// The connection is always closed, no matter what fails at what point
using(readFile("1.txt"), readFile("2.txt"), getConnection(), function(txt1, txt2, conn) {
// use conn and have access to txt1 and txt2
});
```
You can also pass the resources in an array in the first argument. In this case the handler function will only be called with one argument that is the array containing the resolved resources in respective positions in the array. Example:
```js
var connectionPromises = [getConnection(), getConnection()];
using(connectionPromises, function(connections) {
var conn1 = connections[0];
var conn2 = connections[1];
// use conn1 and conn2
}).then(function() {
// Both connections closed by now
})
```
================================================
FILE: docs/docs/api/promiseinspection.md
================================================
---
layout: api
id: promiseinspection
title: PromiseInspection
---
[← Back To API Reference](/docs/api-reference.html)
##PromiseInspection
```js
interface PromiseInspection {
any reason()
any value()
boolean isPending()
boolean isRejected()
boolean isFulfilled()
boolean isCancelled()
}
```
This interface is implemented by `Promise` instances as well as the `PromiseInspection` result given by [.reflect()](.).
================================================
FILE: docs/docs/api/promisification.md
================================================
---
layout: api
id: promisification
title: Promisification
---
[← Back To API Reference](/docs/api-reference.html)
##Promisification
Promisification means converting an existing promise-unaware API to a promise-returning API.
The usual way to use promises in node is to [Promise.promisifyAll](.) some API and start exclusively calling promise returning versions of the APIs methods. E.g.
```js
var fs = require("fs");
Promise.promisifyAll(fs);
// Now you can use fs as if it was designed to use bluebird promises from the beginning
fs.readFileAsync("file.js", "utf8").then(...)
```
Note that the above is an exceptional case because `fs` is a singleton instance. Most libraries can be promisified by requiring the library's classes (constructor functions) and calling promisifyAll on the `.prototype`. This only needs to be done once in the entire application's lifetime and after that you may use the library's methods exactly as they are documented, except by appending the `"Async"`-suffix to method calls and using the promise interface instead of the callback interface.
As a notable exception in `fs`, `fs.existsAsync` doesn't work as expected, because Node's `fs.exists` doesn't call back with error as first argument. More at [#418](.). One possible workaround is using `fs.statAsync`.
Some examples of the above practice applied to some popular libraries:
```js
// The most popular redis module
var Promise = require("bluebird");
Promise.promisifyAll(require("redis"));
```
```js
// The most popular mongodb module
var Promise = require("bluebird");
Promise.promisifyAll(require("mongodb"));
```
```js
// The most popular mysql module
var Promise = require("bluebird");
// Note that the library's classes are not properties of the main export
// so we require and promisifyAll them manually
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
```
```js
// Mongoose
var Promise = require("bluebird");
Promise.promisifyAll(require("mongoose"));
```
```js
// Request
var Promise = require("bluebird");
Promise.promisifyAll(require("request"));
// Use request.getAsync(...) not request(..), it will not return a promise
```
```js
// mkdir
var Promise = require("bluebird");
Promise.promisifyAll(require("mkdirp"));
// Use mkdirp.mkdirpAsync not mkdirp(..), it will not return a promise
```
```js
// winston
var Promise = require("bluebird");
Promise.promisifyAll(require("winston"));
```
```js
// rimraf
var Promise = require("bluebird");
// The module isn't promisified but the function returned is
var rimrafAsync = Promise.promisify(require("rimraf"));
```
```js
// xml2js
var Promise = require("bluebird");
Promise.promisifyAll(require("xml2js"));
```
```js
// jsdom
var Promise = require("bluebird");
Promise.promisifyAll(require("jsdom"));
```
```js
// fs-extra
var Promise = require("bluebird");
Promise.promisifyAll(require("fs-extra"));
```
```js
// prompt
var Promise = require("bluebird");
Promise.promisifyAll(require("prompt"));
```
```js
// Nodemailer
var Promise = require("bluebird");
Promise.promisifyAll(require("nodemailer"));
```
```js
// ncp
var Promise = require("bluebird");
Promise.promisifyAll(require("ncp"));
```
```js
// pg
var Promise = require("bluebird");
Promise.promisifyAll(require("pg"));
```
In all of the above cases the library made its classes available in one way or another. If this is not the case, you can still promisify by creating a throwaway instance:
```js
var ParanoidLib = require("...");
var throwAwayInstance = ParanoidLib.createInstance();
Promise.promisifyAll(Object.getPrototypeOf(throwAwayInstance));
// Like before, from this point on, all new instances + even the throwAwayInstance suddenly support promises
```
See also [`Promise.promisifyAll`](.).
================================================
FILE: docs/docs/api/props.md
================================================
---
layout: api
id: props
title: .props
---
[← Back To API Reference](/docs/api-reference.html)
##.props
```js
.props() -> Promise
```
Same as [Promise.props(this)](.).
================================================
FILE: docs/docs/api/race.md
================================================
---
layout: api
id: race
title: .race
---
[← Back To API Reference](/docs/api-reference.html)
##.race
```js
.race() -> Promise
```
Same as [Promise.race(this)](.).
================================================
FILE: docs/docs/api/reason.md
================================================
---
layout: api
id: reason
title: .reason
---
[← Back To API Reference](/docs/api-reference.html)
##.reason
```js
.reason() -> any
```
Get the rejection reason of this promise. Throws an error if the promise isn't rejected - it is a bug to call this method on an unrejected promise.
You should check if this promise is [.isRejected()](.) in code paths where it's guaranteed that this promise is rejected.
================================================
FILE: docs/docs/api/reduce.md
================================================
---
layout: api
id: reduce
title: .reduce
---
[← Back To API Reference](/docs/api-reference.html)
##.reduce
```js
.reduce(
function(any accumulator, any item, int index, int length) reducer,
[any initialValue]
) -> Promise
```
Same as [Promise.reduce(this, reducer, initialValue)](.).
================================================
FILE: docs/docs/api/reflect.md
================================================
---
layout: api
id: reflect
title: .reflect
---
[← Back To API Reference](/docs/api-reference.html)
##.reflect
```js
.reflect() -> Promise
```
The [`.reflect`](.) method returns a promise that is always successful when this promise is settled. Its fulfillment value is an object that implements the [PromiseInspection](.) interface and reflects the resolution of this promise.
Using `.reflect()` to implement `settleAll` (wait until all promises in an array are either rejected or fulfilled) functionality
```js
var promises = [getPromise(), getPromise(), getPromise()];
Promise.all(promises.map(function(promise) {
return promise.reflect();
})).each(function(inspection) {
if (inspection.isFulfilled()) {
console.log("A promise in the array was fulfilled with", inspection.value());
} else {
console.error("A promise in the array was rejected with", inspection.reason());
}
});
```
Using `.reflect()` to implement `settleProps` (like settleAll for an object's properties) functionality
```js
var object = {
first: getPromise1(),
second: getPromise2()
};
Promise.props(Object.keys(object).reduce(function(newObject, key) {
newObject[key] = object[key].reflect();
return newObject;
}, {})).then(function(object) {
if (object.first.isFulfilled()) {
console.log("first was fulfilled with", object.first.value());
} else {
console.error("first was rejected with", object.first.reason());
}
})
```
================================================
FILE: docs/docs/api/resource-management.md
================================================
---
layout: api
id: resource-management
title: Resource management
---
[← Back To API Reference](/docs/api-reference.html)
##Resource management
Managing resources properly without leaks can be challenging. Simply using `.finally` is not enough as the following example demonstrates:
```js
function doStuff() {
return Promise.all([
connectionPool.getConnectionAsync(),
fs.readFileAsync("file.sql", "utf8")
]).spread(function(connection, fileContents) {
return connection.query(fileContents).finally(function() {
connection.close();
});
}).then(function() {
console.log("query successful and connection closed");
});
}
```
It is very subtle but over time this code will exhaust the entire connection pool and the server needs to be restarted. This is because
reading the file may fail and then of course `.spread` is not called at all and thus the connection is not closed.
One could solve this by either reading the file first or connecting first, and only proceeding if the first step succeeds. However,
this would lose a lot of the benefits of using asynchronity and we might almost as well go back to using simple synchronous code.
We can do better, retaining concurrency and not leaking resources, by using:
* [disposers](disposer.html), objects that wrap a resource and a method to release that resource, together with
* [`Promise.using`](promise.using.html), a function to safely use disposers in a way that automatically calls their release method
```js
var using = Promise.using;
using(getConnection(),
fs.readFileAsync("file.sql", "utf8"), function(connection, fileContents) {
return connection.query(fileContents);
}).then(function() {
console.log("query successful and connection closed");
});
```
Continue by reading about [disposers](disposer.html) and [`Promise.using`](promise.using.html)
================================================
FILE: docs/docs/api/return.md
================================================
---
layout: api
id: return
title: .return
---
[← Back To API Reference](/docs/api-reference.html)
##.return
```js
.return(any value) -> Promise
```
```js
.thenReturn(any value) -> Promise
```
Convenience method for:
```js
.then(function() {
return value;
});
```
in the case where `value` doesn't change its value because its binding time is different than when using a closure.
That means `value` is bound at the time of calling [`.return`](.) so this will not work as expected:
```js
function getData() {
var data;
return query().then(function(result) {
data = result;
}).return(data);
}
```
because `data` is `undefined` at the time `.return` is called.
Function that returns the full path of the written file:
```js
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require("fs"));
var baseDir = process.argv[2] || ".";
function writeFile(path, contents) {
var fullpath = require("path").join(baseDir, path);
return fs.writeFileAsync(fullpath, contents).return(fullpath);
}
writeFile("test.txt", "this is text").then(function(fullPath) {
console.log("Successfully file at: " + fullPath);
});
```
*For compatibility with earlier ECMAScript version, an alias `.thenReturn` is provided for [`.return`](.).*
================================================
FILE: docs/docs/api/some.md
================================================
---
layout: api
id: some
title: .some
---
[← Back To API Reference](/docs/api-reference.html)
##.some
```js
.some(int count) -> Promise
```
Same as [Promise.some(this, count)](.).
================================================
FILE: docs/docs/api/spread.md
================================================
---
layout: api
id: spread
title: .spread
---
[← Back To API Reference](/docs/api-reference.html)
##.spread
```js
.spread(
[function(any values...) fulfilledHandler]
) -> Promise
```
Like calling `.then`, but the fulfillment value _must be_ an array, which is flattened to the formal parameters of the fulfillment handler.
```js
Promise.all([
fs.readFileAsync("file1.txt"),
fs.readFileAsync("file2.txt")
]).spread(function(file1text, file2text) {
if (file1text === file2text) {
console.log("files are equal");
}
else {
console.log("files are not equal");
}
});
```
When chaining `.spread`, returning an array of promises also works:
```js
Promise.delay(500).then(function() {
return [fs.readFileAsync("file1.txt"),
fs.readFileAsync("file2.txt")] ;
}).spread(function(file1text, file2text) {
if (file1text === file2text) {
console.log("files are equal");
}
else {
console.log("files are not equal");
}
});
```
Note that if using ES6, the above can be replaced with [.then()](.) and destructuring:
```js
Promise.delay(500).then(function() {
return [fs.readFileAsync("file1.txt"),
fs.readFileAsync("file2.txt")] ;
}).all().then(function([file1text, file2text]) {
if (file1text === file2text) {
console.log("files are equal");
}
else {
console.log("files are not equal");
}
});
```
Note that [.spread()](.) implicitly does [.all()](.) but the ES6 destructuring syntax doesn't, hence the manual `.all()` call in the above code.
If you want to coordinate several discrete concurrent promises, use [`Promise.join`](.)
================================================
FILE: docs/docs/api/suppressunhandledrejections.md
================================================
---
layout: api
id: suppressunhandledrejections
title: .suppressUnhandledRejections
---
[← Back To API Reference](/docs/api-reference.html)
##.suppressUnhandledRejections
```js
.suppressUnhandledRejections() -> undefined
```
Basically sugar for doing:
```js
somePromise.catch(function(){});
```
Which is needed in case error handlers are attached asynchronously to the promise later, which would otherwise result in premature unhandled rejection reporting.
Example:
```js
var tweets = fetchTweets();
$(document).on("ready", function() {
tweets.then(function() {
// Render tweets
}).catch(function(e) {
alert("failed to fetch tweets because: " + e);
});
});
```
If fetching tweets fails before the document is ready the rejection is reported as unhandled even though it will be eventually handled when the document is ready. This is of course impossible to determine automatically, but you can explicitly do so using `.suppressUnhandledRejections()`:
```js
var tweets = fetchTweets();
tweets.suppressUnhandledRejections();
$(document).on("ready", function() {
tweets.then(function() {
// Render tweets
}).catch(function(e) {
alert("failed to fetch tweets because: " + e);
});
});
```
It should be noted that there is no real need to attach the handlers asynchronously. Exactly the same effect can be achieved with:
```js
fetchTweets()
.finally(function() {
return $.ready.promise();
})
// DOM guaranteed to be ready after this point
.then(function() {
// Render tweets
})
.catch(function(e) {
alert("failed to fetch tweets because: " + e);
});
```
The advantage of using `.suppressUnhandledRejections()` over `.catch(function(){})` is that it doesn't increment the branch count of the promise. Branch counts matter when using cancellation because a promise will only be cancelled if all of its branches want to cancel it.
================================================
FILE: docs/docs/api/synchronous-inspection.md
================================================
---
layout: api
id: synchronous-inspection
title: Synchronous inspection
---
[← Back To API Reference](/docs/api-reference.html)
##Synchronous inspection
Often it is known in certain code paths that a promise is guaranteed to be fulfilled at that point - it would then be extremely inconvenient to use [`.then`](.) to get at the promise's value as the callback is always called asynchronously.
**Note**: In recent versions of Bluebird a design choice was made to expose [.reason()](.) and [.value()](.) as well as other inspection methods on promises directly in order to make the below use case easier to work with. Every promise implements the [PromiseInspection](.) interface.
For example, if you need to use values of earlier promises in the chain, you could nest:
```js
// From Q Docs https://github.com/kriskowal/q/#chaining
// MIT License Copyright 2009–2014 Kristopher Michael Kowal.
function authenticate() {
return getUsername().then(function (username) {
return getUser(username);
// chained because we will not need the user name in the next event
}).then(function (user) {
// nested because we need both user and password next
return getPassword().then(function (password) {
if (user.passwordHash !== hash(password)) {
throw new Error("Can't authenticate");
}
});
});
}
```
Or you could take advantage of the fact that if we reach password validation, then the user promise must be fulfilled:
```js
function authenticate() {
var user = getUsername().then(function(username) {
return getUser(username);
});
return user.then(function(user) {
return getPassword();
}).then(function(password) {
// Guaranteed that user promise is fulfilled, so .value() can be called here
if (user.value().passwordHash !== hash(password)) {
throw new Error("Can't authenticate");
}
});
}
```
In the latter the indentation stays flat no matter how many previous variables you need, whereas with the former each additional previous value would require an additional nesting level.
================================================
FILE: docs/docs/api/tap.md
================================================
---
layout: api
id: tap
title: .tap
---
[← Back To API Reference](/docs/api-reference.html)
##.tap
```js
.tap(function(any value) handler) -> Promise
```
Essentially like `.then()`, except that the value passed in is the value returned.
This means you can insert `.tap()` into a `.then()` chain without affecting what is passed through the chain. (See example below).
Unlike [`.finally`](.) this is not called for rejections.
```js
getUser().tap(function(user) {
//Like in finally, if you return a promise from the handler
//the promise is awaited for before passing the original value through
return recordStatsAsync();
}).then(function(user) {
//user is the user from getUser(), not recordStatsAsync()
});
```
Common case includes adding logging to an existing promise chain:
```js
doSomething()
.then(...)
.then(...)
.then(...)
.then(...)
```
```js
doSomething()
.then(...)
.then(...)
.tap(console.log)
.then(...)
.then(...)
```
*Note: in browsers it is necessary to call `.tap` with `console.log.bind(console)` because console methods can not be called as stand-alone functions.*
================================================
FILE: docs/docs/api/tapcatch.md
================================================
---
layout: api
id: tapCatch
title: .tapCatch
---
[← Back To API Reference](/docs/api-reference.html)
##.tapCatch
`.tapCatch` is a convenience method for reacting to errors without handling them with promises - similar to `finally` but only called on rejections. Useful for logging errors.
It comes in two variants.
- A tapCatch-all variant similar to [`.catch`](.) block. This variant is compatible with native promises.
- A filtered variant (like other non-JS languages typically have) that lets you only handle specific errors. **This variant is usually preferable**.
### `tapCatch` all
```js
.tapCatch(function(any value) handler) -> Promise
```
Like [`.finally`](.) that is not called for fulfillments.
```js
getUser().tapCatch(function(err) {
return logErrorToDatabase(err);
}).then(function(user) {
//user is the user from getUser(), not logErrorToDatabase()
});
```
Common case includes adding logging to an existing promise chain:
#### Rate Limiting
```js
Promise.
try(logIn).
then(respondWithSuccess).
tapCatch(countFailuresForRateLimitingPurposes).
catch(respondWithError);
```
#### Circuit Breakers
```js
Promise.
try(makeRequest).
then(respondWithSuccess).
tapCatch(adjustCircuitBreakerState).
catch(respondWithError);
```
#### Logging
```js
Promise.
try(doAThing).
tapCatch(logErrorsRelatedToThatThing).
then(respondWithSuccess).
catch(respondWithError);
```
*Note: in browsers it is necessary to call `.tapCatch` with `console.log.bind(console)` because console methods can not be called as stand-alone functions.*
### Filtered `tapCatch`
```js
.tapCatch(
class ErrorClass|function(any error),
function(any error) handler
) -> Promise
```
```js
.tapCatch(
class ErrorClass|function(any error),
function(any error) handler
) -> Promise
```
This is an extension to [`.tapCatch`](.) to filter exceptions similarly to languages like Java or C#. Instead of manually checking `instanceof` or `.name === "SomeError"`, you may specify a number of error constructors which are eligible for this tapCatch handler. The tapCatch handler that is first met that has eligible constructors specified, is the one that will be called.
Usage examples include:
#### Rate Limiting
```js
Promise.
try(logIn).
then(respondWithSuccess).
tapCatch(InvalidCredentialsError, countFailuresForRateLimitingPurposes).
catch(respondWithError);
```
#### Circuit Breakers
```js
Promise.
try(makeRequest).
then(respondWithSuccess).
tapCatch(RequestError, adjustCircuitBreakerState).
catch(respondWithError);
```
#### Logging
```js
Promise.
try(doAThing).
tapCatch(logErrorsRelatedToThatThing).
then(respondWithSuccess).
catch(respondWithError);
```
================================================
FILE: docs/docs/api/then.md
================================================
---
layout: api
id: then
title: .then
---
[← Back To API Reference](/docs/api-reference.html)
##.then
```js
.then(
[function(any value) fulfilledHandler],
[function(any error) rejectedHandler]
) -> Promise
```
[Promises/A+ `.then`](http://promises-aplus.github.io/promises-spec/). If you are new to promises, see the [Beginner's Guide]({{ "/docs/beginners-guide.html" | prepend: site.baseurl }}).
================================================
FILE: docs/docs/api/throw.md
================================================
---
layout: api
id: throw
title: .throw
---
[← Back To API Reference](/docs/api-reference.html)
##.throw
```js
.throw(any reason) -> Promise
```
```js
.thenThrow(any reason) -> Promise
```
Convenience method for:
```js
.then(function() {
throw reason;
});
```
Same limitations regarding to the binding time of `reason` to apply as with [`.return`](.).
*For compatibility with earlier ECMAScript version, an alias `.thenThrow` is provided for [`.throw`](.).*
================================================
FILE: docs/docs/api/timeout.md
================================================
---
layout: api
id: timeout
title: .timeout
---
[← Back To API Reference](/docs/api-reference.html)
##.timeout
```js
.timeout(
int ms,
[String message="operation timed out"]
) -> Promise
```
```js
.timeout(
int ms,
[Error error]
) -> 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 a [`TimeoutError`](.) or the `error` as the reason.
When using the first signature, you may specify a custom error message with the `message` parameter.
```js
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync("huge-file.txt").timeout(100).then(function(fileContents) {
}).catch(Promise.TimeoutError, function(e) {
console.log("could not read file within 100ms");
});
```
================================================
FILE: docs/docs/api/timeouterror.md
================================================
---
layout: api
id: timeouterror
title: TimeoutError
---
[← Back To API Reference](/docs/api-reference.html)
##TimeoutError
```js
new TimeoutError(String message) -> TimeoutError
```
Signals that an operation has timed out. Used as a custom cancellation reason in [`.timeout`](.).
================================================
FILE: docs/docs/api/timers.md
================================================
---
layout: api
id: timers
title: Timers
---
[← Back To API Reference](/docs/api-reference.html)
##Timers
Methods to delay and time promises out.
================================================
FILE: docs/docs/api/utility.md
================================================
---
layout: api
id: utility
title: Utility
---
[← Back To API Reference](/docs/api-reference.html)
##Utility
Functions that could potentially be handy in some situations.
================================================
FILE: docs/docs/api/value.md
================================================
---
layout: api
id: value
title: .value
---
[← Back To API Reference](/docs/api-reference.html)
##.value
```js
.value() -> any
```
Get the fulfillment value of this promise. Throws an error if the promise isn't fulfilled - it is a bug to call this method on an unfulfilled promise.
You should check if this promise is [.isFulfilled()](.) in code paths where it's not guaranteed that this promise is fulfilled.
================================================
FILE: docs/docs/async-dialogs.md
================================================
---
id: async-dialogs
title: Async Dialogs
---
[async-dialogs](unfinished-article)
Typically *promises* are used in conjunction with asynchronous tasks such as a
network request or a `setTimeout`; a lesser explored use is dealing with user
input. Since a program has to wait for a user to continue some actions it makes
sense to consider it an asynchronous event.
For comparison I'll start with an example of a *synchronous* user interaction
using `window.prompt` and then move to an *asynchronous* interaction by making
our own DOM based prompt. To begin, here is a template for a simple HTML page:
```html
Async Dislogs Example
The current time is .
Your name is .
```
`window.prompt` blocks the web page from processing while it waits for the user
to enter in data. It has to block because the input is returned and the next
line of code needs that result. But for sake of this tutorial we are going to
convert the typical conditional code into a promise API using a [promise
constructor](api/new-promise.html).
```javascript
function promptPromise(message) {
return new Promise(function(resolve, reject) {
var result = window.prompt(message);
if (result != null) {
resolve(result);
} else {
reject(new Error('User cancelled'));
}
});
}
var button = document.getElementById('action');
var output = document.getElementById('prompt');
button.addEventListener('click', function() {
promptPromise('What is your name?')
.then(function(name) {
output.innerHTML = String(name);
})
.catch(function() {
output.innerHTML = '¯\\_(ツ)_/¯';
});
});
```
[Run example on JSBin][Example1]
This doesn't add much much using `window.prompt`; however, one advantage is the
API that promises provide. In the case where we call `promptPromise(…)` we can
easily react to the result of the dialog without having to worry about how it is
implemented. In our example we've implemented the `window.prompt` but our call
to `promptPromise()` doesn't care. This makes a change to an *asynchronous*
dialog a little more future proof.
To drive home the synchronous nature of the `window.prompt` notice that the time
stops ticking when the prompt dialog is displayed. Let's fix that by making our
own prompt. Since our dialog is just DOM manipulation the page won't be blocked
while waiting for user input.
First add the prompt dialog to the HTML:
```html
foobar
```
We will want to keep the same API so our change will be only to the
`promisePrompt`. It will find the dialog DOM elements, attach events to the
elements, show the dialog box, return a promise that is resolved based on the
attached events, and finally detaches the events and cleans up after itself
(hiding the dialog box for another use later).
```javascript
function promptPromise(message) {
var dialog = document.getElementById('dialog');
var input = dialog.querySelector('input');
var okButton = dialog.querySelector('button.ok');
var cancelButton = dialog.querySelector('button.cancel');
dialog.querySelector('.message').innerHTML = String(message);
dialog.className = '';
return new Promise(function(resolve, reject) {
dialog.addEventListener('click', function handleButtonClicks(e) {
if (e.target.tagName !== 'BUTTON') { return; }
dialog.removeEventListener('click', handleButtonClicks);
dialog.className = 'hidden';
if (e.target === okButton) {
resolve(input.value);
} else {
reject(new Error('User cancelled'));
}
});
});
}
```
[Run example on JSBin][Example2]
Now when the user presses the **Set Name** button the clock continues to update
while the dialog is visible.
Because the `removeEventListener` requires a reference to the original function
that was used with the `addEventListener` it makes it difficult to clean up
after itself without storing the references in a scope higher then the handler
itself. Using a named function we can reference it when a user clicks the
button. To help with performance and to avoid duplicating code the example uses
[event delegation][1] to capture both buttons in one *click* handler.
[1]: https://davidwalsh.name/event-delegate
The same thing can be done with less code using jQuery's [event
namespacing](https://api.jquery.com/on/#event-names).
```javascript
return new Promise(function(resolve, reject) {
$('#okButton').on('click.promptDialog', function() {
resolve(input.value);
});
$('#cancelButton').on('click.promptDialog', reject);
})
.finally(function() {
$('#okButton').off('click.promptDialog');
$('#cancelButton').off('click.promptDialog');
});
```
There are still a few problems with the earlier code example. It feels like it
is doing too much. A *squint* test reveals behavior for showing the dialog, set
the dialog's message, attach two DOM events, construct a promise, event
delegation, hide the dialog, and finally detach DOM events. That is a lot for
one little function. A refactoring can help.
Abstraction is the key here. We will make an *object* (or class) that is
responsible for managing the dialog box. Its interface will manage only two
function references (callbacks): when the user clicks ok and when user clicks
cancel. And it will offer the value when asked.
Using an abstraction like this the `promisePrompt` no longer needs to know
anything about the DOM and concentrates on just providing a promise. This will
also make things easier to create a promised version of a progress bar or
confirmation dialog or any other type of UI that we want to have a value for.
All we will need to do is write a class for that dialog type with the same
interface and just pass that class into our promise making method.
The dialog interface might look like this:
```javascript
var noop = function() {
return this;
};
function Dialog() {
this.setCallbacks(noop, noop);
}
Dialog.prototype.setCallbacks = function(okCallback, cancelCallback) {
this._okCallback = okCallback;
this._cancelCallback = cancelCallback;
return this;
};
Dialog.prototype.waitForUser = function() {
var _this = this;
return new Promise(function(resolve, reject) {
_this.setCallbacks(resolve, reject);
});
};
Dialog.prototype.show = noop;
Dialog.prototype.hide = noop;
```
Initially the Dialog class sets the two callbacks to *noop* functions. It is up
to the child class to call them when necessary. We break down the promise
creation to one function `waitForUser()` that sets the callbacks and returns a
promise. At this level the `show()` and `hide()` are just *noop* functions as
well and will be implemented by the child classes.
Our `PromptDialog` class is responsible for inheriting from `Dialog` and setting
up the required DOM scaffolding and eventually call `this._okCallback` or
`this._cancelCallback` as appropriate.
It might look like this:
```javascript
function PromptDialog() {
Dialog.call(this);
this.el = document.getElementById('dialog');
this.inputEl = this.el.querySelector('input');
this.messageEl = this.el.querySelector('.message');
this.okButton = this.el.querySelector('button.ok');
this.cancelButton = this.el.querySelector('button.cancel');
this.attachDomEvents();
}
PromptDialog.prototype = Object.create(Dialog.prototype);
PromptDialog.prototype.attachDomEvents = function() {
var _this = this;
this.okButton.addEventListener('click', function() {
_this._okCallback(_this.inputEl.value);
});
this.cancelButton.addEventListener('click', function() {
_this._cancelCallback();
});
};
PromptDialog.prototype.show = function(message) {
this.messageEl.innerHTML = String(message);
this.el.className = '';
return this;
};
PromptDialog.prototype.hide = function() {
this.el.className = 'hidden';
return this;
};
```
Notice that use of `return this;` in most of the functions? That pattern will
allow method chaining as you'll see shortly.
This inherits from `Dialog` and stores references to the required DOM elements
that this dialog uses. It then attaches the require DOM events
(`attachDomEvents()`) which eventually call the callbacks. Then it implements
the `show()` and `hide()` methods. Its usage is more flexible and verbose:
```javascript
var output = document.getElementById('prompt');
var prompt = new PromptDialog();
prompt.show('What is your name?')
.waitForUser()
.then(function(name) {
output.innerHTML = String(name);
})
.catch(function() {
output.innerHTML = '¯\\_(ツ)_/¯';
})
.finally(function() {
prompt.hide();
});
```
[Run example on JSBin][Example3]
This abstraction can be expanded on in other ways. For example a notification
dialog:
```javascript
function NotifyDialog() {
Dialog.call(this);
var _this = this;
this.el = document.getElementById('notify-dialog');
this.messageEl = this.el.querySelector('.message');
this.okButton = this.el.querySelector('button.ok');
this.okButton.addEventListener('click', function() {
_this._okCallback();
});
}
NotifyDialog.prototype = Object.create(Dialog.prototype);
NotifyDialog.prototype.show = function(message) {
this.messageEl.innerHTML = String(message);
this.el.className = '';
return this;
};
NotifyDialog.prototype.show = function() {
this.el.className = 'hidden';
return this;
};
```
#### Exercises for the student
1. Write a function that takes a `Dialog` instance and a default value. Have it
return a promise that resolves to the default value if the user clicks
cancel.
2. With the use of abstract classes can the similarities between `PromptDialog`
and `NotifyDialog` be abstracted? Make a sub class of `Dialog` that
abstracts the common DOM code (`DOMDialog`). Then refactor the
`PromptDialog` and `NotifyDialog` to inherate from `DOMDialog` but
references the correct DOM selectors.
## Cancellation
Something missing from the above example is proper error handling. When it comes
to promises it is a best practise to always *reject a promise with an Error* and
not with plain data such as an object, string, number, or null/undefined. The
reasoning for this is promises are best used as a way to regain some of the
syntax you have with the standard `try {} catch() {}` blocks with asynchronous
code.
An advantage of using `Error`s is the ability to test why a promise was rejected
and make decisions on that. This ability is also baked into how Bluebird works.
You can pass in a predicate to the `catch()` block allowing you to have more
than one block based on what `Error` it was rejected with. For example:
```javascript
doSomething().then(function(value) {
// Do something with value or fail with an error.
throw new Error('testing errors');
})
.catch(ArgumentError, function(e) {
console.log('You buggered up something with the arguments.', e);
})
.catch(SyntaxError, function(e) {
console.log('Check your syntax!', e);
})
.catch(function(e) {
// e is an Error object.
console.log('Well something genaric happened.', e);
});
```
In our dialog example perhaps we want to differentiate between a rejected
promise because of some problem (bad AJAX, programming error, etc.) or because
the user pressed the cancel button.
To do this we will have two `catch()` functions one for `UserCanceledError` and
one for any other `Error`. We can make a custom error like so:
```javascript
function UserCanceledError() {
this.name = 'UserCanceledError';
this.message = 'Dialog cancelled';
}
UserCanceledError.prototype = Object.create(Error.prototype);
```
See [this StackOverflow answer](http://stackoverflow.com/a/17891099/227176) for
a more detailed and feature complete way to make custom errors.
Now we can add a `cancel()` reject with this in our event listener:
```javascript
Dialog.prototype.cancel = function() {
this._cancelCallback(new UserCanceledError());
};
…
PromptDialog.prototype.attachDomEvents = function() {
var _this = this;
this.okButton.addEventListener('click', function() {
_this._okCallback(_this.inputEl.value);
});
this.cancelButton.addEventListener('click', function() {
_this.cancel();
});
};
```
And in our usage case we can test for it:
```javascript
// Timeout the dialog in five seconds.
setTimeout(function() { prompt.cancel(); }, 5000);
prompt.show('What is your name?')
.waitForUser()
.then(function(name) {
output.innerHTML = String(name);
})
.catch(UserCanceledError, function() {
output.innerHTML = '¯\\_(ツ)_/¯';
})
.catch(function(e) {
console.log('Something bad happened!', e);
})
.finally(function() {
prompt.hide();
});
```
[Run example on JSBin][Example4]
**NOTE:** Bluebird supports [cancellation](api/cancellation.html) as an optional
feature that is turned off by default. However, its implementation (since
version 3.0) is meant to stop the then and catch callbacks from firing. It is
not helpful in the example of a user cancellation as described here.
## Progress bar
When there are asynchronous tasks that have the ability to notify progress as
they complete it can be tempting to want that in the promise that represents
that task. Unfortunately this is a bit of an anti-pattern. That is because the
point of promises is to represent a value as if it was natural (like it is in
normal synchronous code) and not to be over glorified callback management.
So how then could we represent a progress bar like dialog? Well the answer is to
manage the progress through callbacks outside the promise API. Bluebird has
since [deprecated the progression feature](deprecated-apis.html#progression) and
offers an alternative which I hope to illustrate here.
Another key difference between a *progress bar* dialog and any other dialog
we've discussed here is that a progress bar represents information on another
task and *not* user import. Instead of the program waiting for the user to
provide a value the dialog box is waiting on the program to provide a value
(resolved: 100% complete, rejected: aborted half way through). Because of this
the *progress bar* dialog would have a different interface then the previous
dialogs we've covered. However, there can still be some user interaction so in
essence we are dealing with two promises.
Bluebird has a way to manage more than one promise simultaneously. When you want
to know if more then one promise completes there is a `Promise.all()` function
that takes an array of promises and returns a new promise waiting for them all
to resolve. But if any one is rejected the returned promise is immediately
rejected.
Bluebird also has a `Promise.race()` function which does the same thing but
doesn't wait for all of them to finish. That is what we want. An example how
this might look:
```javascript
function showProgress(otherPromise) {
var progress = new ProgressbarDialog().show('Uploading…');
return Promise.race([otherPromise, promise.waitForUser()])
.finally(function() {
progress.hide();
});
}
```
Here is some example HTML for the Progress Dialog:
```html
```
The JavaScript is the same as the `PromptDialog` only we will add a
`setProgress()` method:
```javascript
function ProgressDialog() {
Dialog.call(this);
this.el = document.getElementById('progress-dialog');
this.messageEl = this.el.querySelector('.message');
this.progressBar = this.el.querySelector('.progress-bar>div');
this.cancelButton = this.el.querySelector('button.cancel');
this.attachDomEvents();
}
ProgressDialog.prototype = Object.create(Dialog.prototype);
ProgressDialog.prototype.attachDomEvents = function() {
var _this = this;
this.cancelButton.addEventListener('click', function() {
_this.cancel();
});
};
ProgressDialog.prototype.show = function(message) {
this.messageEl.innerHTML = String(message);
this.el.className = '';
return this;
};
ProgressDialog.prototype.hide = function() {
this.el.className = 'hidden';
return this;
};
ProgressDialog.prototype.setProgress = function(percent) {
this.progressBar.style.width = percent + '%';
};
```
A common misconception is that promises are a form of callback management. This
is not the case and is why the idea of having a progress callback is not part of
the Promise spec. However, much like the Promise library passes in a `resolve`
and `reject` callback when you create a new promise (`new Promise(…)`) we can do
the same patter for a progress callback.
Now to the fun part. For this tutorial we will *fake* a lengthy file upload by
using `setTimeout`. The intent is to provide a promise and to allow a progress
to be periodically ticked away. We will expect a function to be passed which
is called whenever the progress needs updating. And it returns a promise.
```javascript
function delayedPromise(progressCallback) {
var step = 10;
return new Promise(function(resolve, reject) {
var progress = 0 - step; // So first run of nextTick will set progress to 0
function nextTick() {
if (progress >= 100 ) {
resolve('done');
} else {
progress += step;
progressCallback(progress);
setTimeout(nextTick, 500);
}
}
nextTick();
});
}
```
When we construct our `ProgressDialog` we use the `waitForUser()` method to
capture the user interaction promise and then use `delayedPromise()` to capture
the fake network promise and finally `Promise.reace()` to manage the two
simultaneously and end with a single promise as usual.
```javascript
document.addEventListener('DOMContentLoaded', function() {
var button = document.getElementById('action');
var output = document.getElementById('output');
var prompt = new ProgressDialog();
button.addEventListener('click', function() {
var pendingProgress = true;
var waitForPromise = delayedPromise(function(progress) {
if (pendingProgress) {
prompt.setProgress(progress);
}
});
// Prevent user from pressing button while dialog is visible.
button.disabled = true;
prompt.show('Simulating a file upload.');
Promise.race([waitForPromise, prompt.waitForUser()])
.then(function() {
output.innerHTML = 'Progress completed';
})
.catch(UserCanceledError, function() {
output.innerHTML = 'Progress canceled by user';
})
.catch(function(e) {
console.log('Error', e);
})
.finally(function() {
pendingProgress = false;
button.disabled = false;
prompt.hide();
});
});
});
```
[Run example on JSBin][Example5]
I hope this helps illustrate some concepts available with Promises and a
different perspective on how promises can represent more then just AJAX data.
Although the code may look verbose it does provide the benefit that it is
modular and can be easily changed. A trait difficult to achieve with a more
procedural style.
Happy coding, [@sukima](https://github.com/sukima).
[Example1]: http://jsbin.com/kowama/edit?js,output
[Example2]: http://jsbin.com/fucofu/edit?js,output
[Example3]: http://jsbin.com/wupixi/edit?js,output
[Example4]: http://jsbin.com/yaropo/edit?js,output
[Example5]: http://jsbin.com/bipeve/edit?js,output
================================================
FILE: docs/docs/beginners-guide.md
================================================
---
id: beginners-guide
title: Beginner's Guide
---
[beginners-guide](unfinished-article)
================================================
FILE: docs/docs/benchmarks.md
================================================
---
id: benchmarks
title: Benchmarks
---
Benchmarks have been ran with the following versions of modules.
```
├── async@1.5.2
├── babel@5.8.35
├── davy@1.1.0
├── deferred@0.7.5
├── kew@0.7.0
├── lie@3.0.2
├── neo-async@1.7.3
├── optimist@0.6.1
├── promise@7.1.1
├── q@1.4.1
├── rsvp@3.2.1
├── streamline@2.0.16
├── streamline-runtime@1.0.38
├── text-table@0.2.0
├── vow@0.4.12
└── when@3.7.7
```
###1\. DoxBee sequential
This is Gorki Kosev's benchmark used in the article [Analysis of generators and other async patterns in node](http://spion.github.io/posts/analysis-generators-and-other-async-patterns-node.html). The benchmark emulates a situation where N=10000 requests are being made concurrently to execute some mixed async/sync action with fast I/O response times.
This is a throughput benchmark.
Every implementation runs in a freshly created isolated process which is warmed up to the benchmark code before timing it. The memory column represents the highest snapshotted RSS memory (as reported by `process.memoryUsage().rss`) during processing.
Command: `./bench doxbee` (needs cloned repository)
The implementations for this benchmark are found in [`benchmark/doxbee-sequential`](https://github.com/petkaantonov/bluebird/tree/master/benchmark/doxbee-sequential) directory.
```
results for 10000 parallel executions, 1 ms per I/O op
file time(ms) memory(MB)
callbacks-baseline.js 116 33.98
callbacks-suguru03-neo-async-waterfall.js 145 43.81
promises-bluebird-generator.js 183 42.35
promises-bluebird.js 214 43.41
promises-cujojs-when.js 312 64.37
promises-then-promise.js 396 74.33
promises-tildeio-rsvp.js 414 84.80
promises-native-async-await.js 422 104.23
promises-ecmascript6-native.js 424 92.12
generators-tj-co.js 444 90.98
promises-lvivski-davy.js 480 114.46
callbacks-caolan-async-waterfall.js 520 109.01
promises-dfilatov-vow.js 612 134.38
promises-obvious-kew.js 725 208.63
promises-calvinmetcalf-lie.js 730 164.96
streamline-generators.js 809 154.36
promises-medikoo-deferred.js 913 178.51
observables-pozadi-kefir.js 991 194.00
streamline-callbacks.js 1127 196.54
observables-Reactive-Extensions-RxJS.js 1906 268.41
observables-caolan-highland.js 6887 662.08
promises-kriskowal-q.js 8533 435.51
observables-baconjs-bacon.js.js 21282 882.61
Platform info:
Linux 4.4.0-79-generic x64
Node.JS 8.6.0
V8 6.0.287.53
Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz × 4
```
###2\. Parallel
This made-up scenario runs 25 shimmed queries in parallel per each request (N=10000) with fast I/O response times.
This is a throughput benchmark.
Every implementation runs in a freshly created isolated process which is warmed up to the benchmark code before timing it. The memory column represents the highest snapshotted RSS memory (as reported by `process.memoryUsage().rss`) during processing.
Command: `./bench parallel` (needs cloned repository)
The implementations for this benchmark are found in [`benchmark/madeup-parallel`](https://github.com/petkaantonov/bluebird/tree/master/benchmark/madeup-parallel) directory.
```
results for 10000 parallel executions, 1 ms per I/O op
file time(ms) memory(MB)
callbacks-baseline.js 274 75.11
callbacks-suguru03-neo-async-parallel.js 320 88.84
promises-bluebird.js 407 107.25
promises-bluebird-generator.js 432 113.19
callbacks-caolan-async-parallel.js 550 154.27
promises-cujojs-when.js 648 168.65
promises-ecmascript6-native.js 1145 308.87
promises-lvivski-davy.js 1153 257.36
promises-native-async-await.js 1260 323.68
promises-then-promise.js 1372 313.24
promises-tildeio-rsvp.js 1435 398.73
promises-medikoo-deferred.js 1626 306.02
promises-calvinmetcalf-lie.js 1805 351.21
promises-dfilatov-vow.js 2492 558.25
promises-obvious-kew.js 3403 784.61
streamline-generators.js 13068 919.24
streamline-callbacks.js 25509 1141.57
Platform info:
Linux 4.4.0-79-generic x64
Node.JS 8.6.0
V8 6.0.287.53
Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz × 4
```
###3\. Latency benchmarks
For reasonably fast promise implementations latency is going to be fully determined by the scheduler being used and is therefore not interesting to benchmark. [JSPerfs](https://jsperf.com/) that benchmark promises tend to benchmark latency.
================================================
FILE: docs/docs/changelog.md
================================================
---
id: changelog
title: Changelog
---
## 3.7.2 (2019-11-28)
Bugfixes:
- Fixes firefox settimeout not initialized error \([#1623](.)\)
## 3.7.1 (2019-10-15)
Features:
- feature
Bugfixes:
- Fix \([#1614](.)\)
- Fix \([#1613](.)\)
- Fix \([#1616](.)\)
## 3.7.0 (2019-10-01)
Features:
- Add [Promise.allSettled](.) method \([#1606](.)\)
## 3.6.0 (2019-10-01)
Features:
- Add support for AsyncResource \([#1403](.)\)
Bugfixes:
- Fix [.reduce](.) generating unhandled rejection events \([#1501](.)\)
- Fix [Promise.reduce](.) generating unhandled rejction events \([#1502](.)\)
- Fix [.map](.) and [.filter](.) generating unhandled rejection events \([#1487](.)\)
- Fix [Promise.map](.) unhandled rejection events \([#1489](.)\)
- Fix cancel skipping upward propagation \([#1459](.)\)
- Fix loadTimes deprecation \([#1505](.)\)
- Fix [Promise.each](.) maximum stack exceeded error \([#1326](.)\)
- Make PromiseRejectionEvent confrom to spec \([#1509](.)\)
- Fix false unhandled rejection events \([#1468](.)\)
## 3.5.5 (2019-05-24)
Features:
- Added Symbol.toStringTag support to Promise \([#1421](.)\)
Bugfixes:
- Fix error in IE9 \([#1591](.), [#1592](.)\)
- Fix error with undefined stack trace \([#1537](.)\)
- Fix [.catch](.) throwing an error later rather than immediately when passed non-function handler \([#1517](.)\)
## 3.5.4 (2019-04-03)
- Proper version check supporting VSCode\([#1576](.)\)
## 3.5.3 (2018-11-06)
Bugfixes:
- Update acorn dependency
## 3.5.2 (2018-09-03)
Bugfixes:
- Fix `PromiseRejectionEvent` to contain `.reason` and `.promise` properties. \([#1509](.), [#1464](.)\)
- Fix promise chain retaining memory until the entire chain is resolved \([#1544](.), [#1529](.)\)
## 3.5.1 (2017-10-04)
Bugfixes:
- Fix false positive unhandled rejection when using async await \([#1404](.)\)
- Fix false positive when reporting error as non-error \([#990](.)\)
## 3.5.0 (2017-03-03)
Features:
- Added new method: [.tapCatch](.) \([#1220](.)\)
Bugfixes:
- Fixed streamline benchmarks \([#1233](.)\)
- Fixed yielding a function calling the function \([#1314](.), [#1315](.)\)
- Fixed confusing error message when calling [.catch](.) with non function predicate \([#1350](.)\)
- Fixed [.props](.) resolving to empty object when called with empty `Map` \([#1338](.)\)
- Fixed confusing error message when invoking `Promise` directly without `new` \([#1320](.)\)
- Added dedicated webpack entry point \([#1318](.)\)
## 3.4.7 (2016-12-22)
- Promise config returns reference to Bluebird library
- Updated logo
- Benchmark fix
- Don't drop syntaxerror context from stack traces
- Fix environment variables sometimes causing long stack traces to be enabled
## 3.4.6 (2016-09-01)
Bugfixes:
- Fix [Promise.map](.) and [.map](.) not always calling the callback asynchronously \([#1148](.)\)
## 3.4.5 (2016-08-31)
Bugfixes:
- Fix unhandled error regression introduced in 3.4.3 [#1217](.)
## 3.4.4 (2016-08-30)
Bugfixes:
- Fix benchmark parallel in node 6 [#1165](.)
- Fix memory leak with Promise.each [#1057](.)
- Fix thenable passed to .return being evaluated too early [#1210](.)
- Fix "unhandledrejection" event not having .detail field when using DOM3 event listener api [#1209](.)
- Fix [Promise.join](.) not ensuring asynchronous callback [#1153](.)
- Fix domains leaking when synchronous error is thrown while a domain is active [#1125](.)
## 3.4.3 (2016-08-25)
Bugfixes:
- The "a promise was created in a handler but not returned from it" warning now highlights the file, line and column where the return statement is missing.
- The "a promise was created in a handler but not returned from it" warning now adds the bluebird API method used to create the non-returned promise at the top of the warning stack
## 3.4.2 (2016-08-24)
Bugfixes:
- Add missing link to unhandled warning docs \([#1205](.)\)
- Fix [Promise.delay](.) not having a long stack trace \([#1182](.)\)
- Fix false unhandled rejection when a rejected promise originating from one copy of bluebird is passed to another copy's [.return](.) or [.catchReturn](.) \([#1186](.)\)
- Fix Promise.resolve is not a function error \([#1192](.)\)
- Fix global events not being fired through DOM 3 API inside a worker \([#1190](.)\)
- Fix .cancel() not immediately marking a promise as being cancelled if it has cancellable parent \([#1187](.)\)
- Fix maximum callstack exceeded with [Promise.coroutine](.) \([#1170](.)\)
## 3.4.1 (2016-06-17)
Features:
- Added [Promise.getNewLibraryCopy](.)
## 3.4.0 (2016-05-17)
Features:
- Add `Promise.version` which tells the bluebird version as a string e.g. `"3.4.0"` ([#1042](.)).
- [.map](.), [Promise.map](.), [.filter](.) and [Promise.filter](.) now return rejected promise when inappropriate options argument is passed ([#1097](.)).
Bugfixes:
- Fix bug where callback to [.disposer](.) is not called if the resource is `null` ([#1099](.)).
- Fix bug where assimilating thenable throws unexpectedly when using hostile host objects as thenables ([#1104](.)).
## 3.3.5 (2016-04-12)
Bugfixes:
- Fix then sometimes not being called on iOS/Firefox ([#1022](.)).
- Fix custom schedulers not being called when using promisified functions ([#1023](.)).
- Fix unexpected error being thrown when promisifed function is called with no arguments ([#1063](.)).
## 3.3.4 (2016-03-07)
Features:
- Warnings about created promises that are not returned are no longer given if the handler promise has not been chained. This should reduce the amount of false positives with this warning.
## 3.3.3 (2016-02-25)
Bugfixes:
- Fix stack overflow error when a promise returned by promisified function rejects early in a huge array when using [Promise.mapSeries](.) or [Promise.each](.)
## 3.3.2 (2016-02-25)
Bugfixes:
- Fix missing newline in stack trace reported by [.done()](.) ([#1020](.)).
- Detect deep circular resolutions
## 3.3.1 (2016-02-13)
Bugfixes:
- Fix crash when cancelling a [.tap()](.) handler promise ([#1006](.)).
## 3.3.0 (2016-02-12)
Features:
- Cancelling Promise returned from [Promise.delay()](.) and [.delay()](.) now calls `clearTimeout` ([#1000](.))
- Add [monitoring and lifecycle hooks](http://bluebirdjs.com/docs/features.html#promise-monitoring)
- Add `'warning'` hook for warnings ([#980](.))
Bugfixes:
- Fix warnings for "promise was rejected with non-error" being output when promises are rejected with errors from different realm ([#990](.))
## 3.2.2 (2016-02-05)
Bugfixes:
- Make build script's output work without TTY
## 3.2.1 (2016-02-01)
Bugfixes:
- Revert monitoring feature due to crash in browser
## 3.2.0 (2016-02-01)
- Broken build
## 3.1.5 (2016-01-26)
Dummy release to trigger CDN update.
## 3.1.4 (2016-01-25)
Bugfixes:
- Fix broken npm prepublish script release
## 3.1.3 (2016-01-25)
Bugfixes:
- Fix generators crashing in node 0.12 ([#978](.))
- Add minimal build files to build ([#976](.), [#757](.))
## 3.1.2 (2016-01-23)
Features:
- [.timeout()](.) now `clearTimeout`s the timer if the resulting promise is cancelled ([#926](.))
- [Promise.coroutine](.) now returns function with same `.length` as the original function ([#927](.), [#933](.))
Bugfixes:
- Fix long stack traces not working when promise is created from [Promise.fromCallback](.) ([#971](.))
- Fix [.finally()](.) handlers not being called when promise is cancelled while a domain is active ([#963](.))
- Fix [.timeout()](.) trying to cancel a promise even if cancellation is disabled ([#970](.))
## 3.1.1 (2015-12-16)
Bugfixes:
- Disable wForgottenWarning when all warnings are disabled
## 3.1.0 (2015-12-16)
Features:
- Added ability to configure the [forgotten return statement](http://bluebirdjs.com/docs/warning-explanations.html#warning-a-promise-was-created-in-a-handler-but-none-were-returned-from-it) warning separately \([#920](.)\).
Bugfixes:
- Fixed the bug where returning a value from [.finally](.) or [.tap](.) handler did not make a warning about a forgotten return go away \([#846](.)\).
- Fixed the bug where setTimeout is used in Chrome instead of MutationObserver \([#915](.)\)
- Fixed the bug where using [.bind](.) suppressed unhandled rejections \([#841](.)\)
## 3.0.6 (2015-12-01)
Bugfixes:
- Fix [.timeout()](.) not cancelling parent \([#891](.)\)
- Fix long stack traces when using [Promise.resolve()](.) \([#861](.)\)
- Fix [Promise.config()](.) not disabling long stack traces when passing `longStackTraces: false` \([#897](.)\)
## 3.0.5 (2015-11-01)
Bugfixes:
- Added [forgotten return warnings](http://bluebirdjs.com/docs/warning-explanations.html#warning-a-promise-was-created-in-a-handler-but-none-were-returned-from-it) to [Promise.try](.) and [Promise.method](.)
## 3.0.4 (2015-11-01)
Bugfixes:
- The stack trace for [forgotten return warnings](http://bluebirdjs.com/docs/warning-explanations.html#warning-a-promise-was-created-in-a-handler-but-none-were-returned-from-it) is more useful now.
## 3.0.3 (2015-11-01)
Bugfixes:
- 3rd party libraries rejecting promises with non-errors no longer causes warnings
- When `NODE_ENV` environment variable is `"development"` setting `BLUEBIRD_DEBUG` environment variable to `0` can now be used to disable debug mode
## 3.0.2 (2015-10-29)
Bugfixes:
- Fix crash when using node.js domains [#829](.)
## 3.0.1 (2015-10-28)
See [New in 3.0](new-in-bluebird-3.html).
## 3.0.0 (2015-10-27)
See [New in 3.0](new-in-bluebird-3.html).
## 2.11.0 (2016-08-30)
Features:
- feature
Bugfixes:
- bugfix
## 2.10.2 (2015-10-01)
Features:
- [.timeout()](.) now takes a custom error object as second argument
## 2.10.1 (2015-09-21)
- Fix error "Cannot promisify an API that has normal methods with 'Async'-suffix" when promisifying certain objects with a custom promisifier
## 2.10.0 (2015-09-08)
Features:
- `Promise.using` can now take the promises-for-resources as an array ([#733](.)).
- Browser builds for minimal core are now hosted on CDN ([#724](.)).
Bugfixes:
- Disabling debug mode with `BLUEBIRD_DEBUG=0` environment variable now works ([#719](.)).
- Fix unhandled rejection reporting when passing rejected promise to `.return()` ([#721](.)).
- Fix unbound promise's then handlers being called with wrong `this` value ([#738](.)).
## 2.9.34 (2015-07-15)
Bugfixes:
- Correct domain for .map, .each, .filter, .reduce callbacks ([#701](.)).
- Preserve bound-with-promise promises across the entire chain ([#702](.)).
## 2.9.33 (2015-07-09)
Bugfixes:
- Methods on `Function.prototype` are no longer promisified ([#680](.)).
## 2.9.32 (2015-07-03)
Bugfixes:
- Fix `.return(primitiveValue)` returning a wrapped version of the primitive value when a Node.js domain is active ([#689](.)).
## 2.9.31 (2015-07-03)
Bugfixes:
- Fix Promises/A+ compliance issue regarding circular thenables: the correct behavior is to go into an infinite loop instead of warning with an error (Fixes [#682](.)).
- Fix "(node) warning: possible EventEmitter memory leak detected" ([#661](.)).
- Fix callbacks sometimes being called with a wrong node.js domain ([#664](.)).
- Fix callbacks sometimes not being called at all in iOS 8.1 WebApp mode ([#666](.), [#687](.)).
## 2.9.30 (2015-06-14)
Bugfixes:
- Fix regression with `promisifyAll` not promisifying certain methods
## 2.9.29 (2015-06-14)
Bugfixes:
- Improve `promisifyAll` detection of functions that are class constructors. Fixes mongodb 2.x promisification.
## 2.9.28 (2015-06-14)
Bugfixes:
- Fix handled rejection being reported as unhandled in certain scenarios when using [.all](.) or [Promise.join](.) ([#645](.))
- Fix custom scheduler not being called in Google Chrome when long stack traces are enabled ([#650](.))
## 2.9.27 (2015-05-30)
Bugfixes:
- Fix `sinon.useFakeTimers()` breaking scheduler ([#631](.))
Misc:
- Add nw testing facilities (`node tools/test --nw`)
## 2.9.26 (2015-05-25)
Bugfixes:
- Fix crash in NW [#624](.)
- Fix [`.return()`](.) not supporting `undefined` as return value [#627](.)
## 2.9.25 (2015-04-28)
Bugfixes:
- Fix crash in node 0.8
## 2.9.24 (2015-04-02)
Bugfixes:
- Fix not being able to load multiple bluebird copies introduced in 2.9.22 ([#559](.), [#561](.), [#560](.)).
## 2.9.23 (2015-04-02)
Bugfixes:
- Fix node.js domain propagation ([#521](.)).
## 2.9.22 (2015-04-02)
- Fix `.promisify` crashing in phantom JS ([#556](.))
## 2.9.21 (2015-03-30)
- Fix error object's `'stack'`' overwriting causing an error when its defined to be a setter that throws an error ([#552](.)).
## 2.9.20 (2015-03-29)
Bugfixes:
- Fix regression where there is a long delay between calling `.cancel()` and promise actually getting cancelled in Chrome when long stack traces are enabled
## 2.9.19 (2015-03-29)
Bugfixes:
- Fix crashing in Chrome when long stack traces are disabled
## 2.9.18 (2015-03-29)
Bugfixes:
- Fix settlePromises using trampoline
## 2.9.17 (2015-03-29)
Bugfixes:
- Fix Chrome DevTools async stack traceability ([#542](.)).
## 2.9.16 (2015-03-28)
Features:
- Use setImmediate if available
## 2.9.15 (2015-03-26)
Features:
- Added `.asCallback` alias for `.nodeify`.
Bugfixes:
- Don't always use nextTick, but try to pick up setImmediate or setTimeout in NW. Fixes [#534](.), [#525](.)
- Make progress a core feature. Fixes [#535](.) Note that progress has been removed in 3.x - this is only a fix necessary for 2.x custom builds.
## 2.9.14 (2015-03-12)
Bugfixes:
- Always use process.nextTick. Fixes [#525](.)
## 2.9.13 (2015-02-27)
Bugfixes:
- Fix .each, .filter, .reduce and .map callbacks being called synchornously if the input is immediate. ([#513](.))
## 2.9.12 (2015-02-19)
Bugfixes:
- Fix memory leak introduced in 2.9.0 ([#502](.))
## 2.9.11 (2015-02-19)
Bugfixes:
- Fix [#503](.)
## 2.9.10 (2015-02-18)
Bugfixes:
- Fix [#501](.)
## 2.9.9 (2015-02-12)
Bugfixes:
- Fix `TypeError: Cannot assign to read only property 'length'` when jsdom has declared a read-only length for all objects to inherit.
## 2.9.8 (2015-02-10)
Bugfixes:
- Fix regression introduced in 2.9.7 where promisify didn't properly dynamically look up methods on `this`
## 2.9.7 (2015-02-08)
Bugfixes:
- Fix `promisify` not retaining custom properties of the function. This enables promisifying the `"request"` module's export function and its methods at the same time.
- Fix `promisifyAll` methods being dependent on `this` when they are not originally dependent on `this`. This enables e.g. passing promisified `fs` functions directly as callbacks without having to bind them to `fs`.
- Fix `process.nextTick` being used over `setImmediate` in node.
## 2.9.6 (2015-02-02)
Bugfixes:
- Node environment detection can no longer be fooled
## 2.9.5 (2015-02-02)
Misc:
- Warn when [`.then()`](.) is passed non-functions
## 2.9.4 (2015-01-30)
Bugfixes:
- Fix [.timeout()](.) not calling `clearTimeout` with the proper handle in node causing the process to wait for unneeded timeout. This was a regression introduced in 2.9.1.
## 2.9.3 (2015-01-27)
Bugfixes:
- Fix node-webkit compatibility issue ([#467](https://github.com/petkaantonov/bluebird/pull/467))
- Fix long stack trace support in recent firefox versions
## 2.9.2 (2015-01-26)
Bugfixes:
- Fix critical bug regarding to using promisifyAll in browser that was introduced in 2.9.0 ([#466](https://github.com/petkaantonov/bluebird/issues/466)).
Misc:
- Add `"browser"` entry point to package.json
## 2.9.1 (2015-01-24)
Features:
- If a bound promise is returned by the callback to [`Promise.method`](.) and [`Promise.try`](.), the returned promise will be bound to the same value
## 2.9.0 (2015-01-24)
Features:
- Add [`Promise.fromNode`](.)
- Add new paramter `value` for [`Promise.bind`](.)
Bugfixes:
- Fix several issues with [`cancellation`](.) and [`.bind()`](.) interoperation when `thisArg` is a promise or thenable
- Fix promises created in [`disposers`](.) not having proper long stack trace context
- Fix [`Promise.join`](.) sometimes passing the passed in callback function as the last argument to itself.
Misc:
- Reduce minified full browser build file size by not including unused code generation functionality.
- Major internal refactoring related to testing code and source code file layout
## 2.8.2 (2015-01-20)
Features:
- [Global rejection events](https://github.com/petkaantonov/bluebird/blob/master/API.md#global-rejection-events) are now fired both as DOM3 events and as legacy events in browsers
## 2.8.1 (2015-01-20)
Bugfixes:
- Fix long stack trace stiching consistency when rejected from thenables
## 2.8.0 (2015-01-19)
Features:
- Major debuggability improvements:
- Long stack traces have been re-designed. They are now much more readable,
succint, relevant and consistent across bluebird features.
- Long stack traces are supported now in IE10+
## 2.7.1 (2015-01-15)
Bugfixes:
- Fix [#447](.)
## 2.7.0 (2015-01-15)
Features:
- Added more context to stack traces originating from coroutines ([#421](https://github.com/petkaantonov/bluebird/issues/421))
- Implemented [global rejection events](https://github.com/petkaantonov/bluebird/blob/master/API.md#global-rejection-events) ([#428](https://github.com/petkaantonov/bluebird/issues/428), [#357](https://github.com/petkaantonov/bluebird/issues/357))
- [Custom promisifiers](https://github.com/petkaantonov/bluebird/blob/master/API.md#option-promisifier) are now passed the default promisifier which can be used to add enhancements on top of normal node promisification
- [Promisification filters](https://github.com/petkaantonov/bluebird/blob/master/API.md#option-filter) are now passed `passesDefaultFilter` boolean
Bugfixes:
- Fix `.noConflict()` call signature ([#446]())
- Fix `Promise.method`ified functions being called with `undefined` when they were called with no arguments
## 2.6.4 (2015-01-12)
Bugfixes:
- `OperationalErrors` thrown by promisified functions retain custom properties, such as `.code` and `.path`.
## 2.6.3 (2015-01-12)
Bugfixes:
- Fix [#429](https://github.com/petkaantonov/bluebird/issues/429)
- Fix [#432](https://github.com/petkaantonov/bluebird/issues/432)
- Fix [#433](https://github.com/petkaantonov/bluebird/issues/433)
## 2.6.2 (2015-01-07)
Bugfixes:
- Fix [#426](https://github.com/petkaantonov/bluebird/issues/426)
## 2.6.1 (2015-01-07)
Bugfixes:
- Fixed built browser files not being included in the git tag release for bower
## 2.6.0 (2015-01-06)
Features:
- Significantly improve parallel promise performance and memory usage (+50% faster, -50% less memory)
## 2.5.3 (2014-12-30)
## 2.5.2 (2014-12-29)
Bugfixes:
- Fix bug where already resolved promise gets attached more handlers while calling its handlers resulting in some handlers not being called
- Fix bug where then handlers are not called in the same order as they would run if Promises/A+ 2.3.2 was implemented as adoption
- Fix bug where using `Object.create(null)` as a rejection reason would crash bluebird
## 2.5.1 (2014-12-29)
Bugfixes:
- Fix `.finally` throwing null error when it is derived from a promise that is resolved with a promise that is resolved with a promise
## 2.5.0 (2014-12-28)
Features:
- [`.get`](.) now supports negative indexing.
Bugfixes:
- Fix bug with `Promise.method` wrapped function returning a promise that never resolves if the function returns a promise that is resolved with another promise
- Fix bug with `Promise.delay` never resolving if the value is a promise that is resolved with another promise
## 2.4.3 (2014-12-28)
Bugfixes:
- Fix memory leak as described in [this Promises/A+ spec issue](https://github.com/promises-aplus/promises-spec/issues/179).
## 2.4.2 (2014-12-21)
Bugfixes:
- Fix bug where spread rejected handler is ignored in case of rejection
- Fix synchronous scheduler passed to `setScheduler` causing infinite loop
## 2.4.1 (2014-12-20)
Features:
- Error messages now have links to wiki pages for additional information
- Promises now clean up all references (to handlers, child promises etc) as soon as possible.
## 2.4.0 (2014-12-18)
Features:
- Better filtering of bluebird internal calls in long stack traces, especially when using minified file in browsers
- Small performance improvements for all collection methods
- Promises now delete references to handlers attached to them as soon as possible
- Additional stack traces are now output on stderr/`console.warn` for errors that are thrown in the process/window from rejected `.done()` promises. See [#411](https://github.com/petkaantonov/bluebird/issues/411)
## 2.3.11 (2014-10-31)
Bugfixes:
- Fix [#371](https://github.com/petkaantonov/bluebird/issues/371), [#373](https://github.com/petkaantonov/bluebird/issues/373)
## 2.3.10 (2014-10-28)
Features:
- `Promise.method` no longer wraps primitive errors
- `Promise.try` no longer wraps primitive errors
## 2.3.7 (2014-10-25)
Bugfixes:
- Fix [#359](https://github.com/petkaantonov/bluebird/issues/359), [#362](https://github.com/petkaantonov/bluebird/issues/362) and [#364](https://github.com/petkaantonov/bluebird/issues/364)
## 2.3.6 (2014-10-15)
Features:
- Implement [`.reflect()`](.)
## 2.3.5 (2014-10-06)
Bugfixes:
- Fix issue when promisifying methods whose names contain the string 'args'
## 2.3.4 (2014-09-27)
- `P` alias was not declared inside WebWorkers
## 2.3.3 (2014-09-27)
Bugfixes:
- Fix [#318](https://github.com/petkaantonov/bluebird/issues/318), [#314](https://github.com/petkaantonov/bluebird/issues/#314)
## 2.3.2 (2014-08-25)
Bugfixes:
- `P` alias for `Promise` now exists in global scope when using browser builds without a module loader, fixing an issue with firefox extensions
## 2.3.1 (2014-08-23)
Features:
- `.using` can now be used with disposers created from different bluebird copy
## 2.3.0 (2014-08-13)
Features:
- [`.bind()`](.) and [`Promise.bind()`](.) now await for the resolution of the `thisArg` if it's a promise or a thenable
Bugfixes:
- Fix [#276](https://github.com/petkaantonov/bluebird/issues/276)
## 2.2.2 (2014-07-14)
- Fix [#259](https://github.com/petkaantonov/bluebird/issues/259)
## 2.2.1 (2014-07-07)
- Fix multiline error messages only showing the first line
## 2.2.0 (2014-07-07)
Bugfixes:
- `.any` and `.some` now consistently reject with RangeError when input array contains too few promises
- Fix iteration bug with `.reduce` when input array contains already fulfilled promises
## 2.1.3 (2014-06-18)
Bugfixes:
- Fix [#235](https://github.com/petkaantonov/bluebird/issues/235)
## 2.1.2 (2014-06-15)
Bugfixes:
- Fix [#232](https://github.com/petkaantonov/bluebird/issues/232)
## 2.1.1 (2014-06-11)
## 2.1.0 (2014-06-11)
Features:
- Add [`promisifier`](.) option to `Promise.promisifyAll()`
- Improve performance of `.props()` and collection methods when used with immediate values
Bugfixes:
- Fix a bug where .reduce calls the callback for an already visited item
- Fix a bug where stack trace limit is calculated to be too small, which resulted in too short stack traces
Add undocumented experimental `yieldHandler` option to `Promise.coroutine`
## 2.0.7 (2014-06-08)
## 2.0.6 (2014-06-07)
## 2.0.5 (2014-06-05)
## 2.0.4 (2014-06-05)
## 2.0.3 (2014-06-05)
## 2.0.2 (2014-06-04)
## 2.0.1 (2014-06-04)
## 2.0.0 (2014-06-04)
#What's new in 2.0
- [Resource management](api-reference.html#resource-management) - never leak resources again
- [Promisification](api-reference.html#promisification) on steroids - entire modules can now be promisified with one line of code
- [`.map()`](.), [`.each()`](.), [`.filter()`](.), [`.reduce()`](.) reimagined from simple sugar to powerful concurrency coordination tools
- [API Documentation](api-reference.html) has been reorganized and more elaborate examples added
- Deprecated [progression](#progression-migration) and [deferreds](#deferred-migration)
- Improved performance and readability
Features:
- Added [`using()`](.) and [`disposer()`](.)
- [`.map()`](.) now calls the handler as soon as items in the input array become fulfilled
- Added a concurrency option to [`.map()`](.)
- [`.filter()`](.) now calls the handler as soon as items in the input array become fulfilled
- Added a concurrency option to [`.filter()`](.)
- [`.reduce()`](.) now calls the handler as soon as items in the input array become fulfilled, but in-order
- Added [`.each()`](.)
- [`Promise.resolve()`](.) behaves like `Promise.cast`. `Promise.cast` deprecated.
- [Synchronous inspection](api-reference.html#synchronous-inspection): Removed `.inspect()`, added [`.value()`](.) and [`.reason()`](.)
- [`Promise.join()`](.) now takes a function as the last argument
- Added [`Promise.setScheduler()`](.)
- [`.cancel()`](.) supports a custom cancellation reason
- [`.timeout()`](.) now cancels the promise instead of rejecting it
- [`.nodeify()`](.) now supports passing multiple success results when mapping promises to nodebacks
- Added `suffix` and `filter` options to [`Promise.promisifyAll()`](.)
Breaking changes:
- Sparse array holes are not skipped by collection methods but treated as existing elements with `undefined` value
- `.map()` and `.filter()` do not call the given mapper or filterer function in any specific order
- Removed the `.inspect()` method
- Yielding an array from a coroutine is not supported by default. You can use [`coroutine.addYieldHandler()`](.) to configure the old behavior (or any behavior you want).
- [`.any()`](.) and [`.some()`](.) no longer use an array as the rejection reason. [`AggregateError`](.) is used instead.
## 1.2.4 (2014-04-27)
Bugfixes:
- Fix promisifyAll causing a syntax error when a method name is not a valid identifier
- Fix syntax error when es5.js is used in strict mode
## 1.2.3 (2014-04-17)
Bugfixes:
- Fix [#179](https://github.com/petkaantonov/bluebird/issues/179)
## 1.2.2 (2014-04-09)
Bugfixes:
- Promisified methods from promisifyAll no longer call the original method when it is overriden
- Nodeify doesn't pass second argument to the callback if the promise is fulfilled with `undefined`
## 1.2.1 (2014-03-31)
Bugfixes:
- Fix [#168](https://github.com/petkaantonov/bluebird/issues/168)
## 1.2.0 (2014-03-29)
Features:
- New method: [`.value()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#value---dynamic)
- New method: [`.reason()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#reason---dynamic)
- New method: [`Promise.onUnhandledRejectionHandled()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#promiseonunhandledrejectionhandledfunction-handler---undefined)
- `Promise.map()`, `.map()`, `Promise.filter()` and `.filter()` start calling their callbacks as soon as possible while retaining a correct order. See [`8085922f`](https://github.com/petkaantonov/bluebird/commit/8085922fb95a9987fda0cf2337598ab4a98dc315).
Bugfixes:
- Fix [#165](https://github.com/petkaantonov/bluebird/issues/165)
- Fix [#166](https://github.com/petkaantonov/bluebird/issues/166)
## 1.1.1 (2014-03-18)
Bugfixes:
- [#138](https://github.com/petkaantonov/bluebird/issues/138)
- [#144](https://github.com/petkaantonov/bluebird/issues/144)
- [#148](https://github.com/petkaantonov/bluebird/issues/148)
- [#151](https://github.com/petkaantonov/bluebird/issues/151)
## 1.1.0 (2014-03-08)
Features:
- Implement [`Promise.prototype.tap()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#tapfunction-handler---promise)
- Implement [`Promise.coroutine.addYieldHandler()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#promisecoroutineaddyieldhandlerfunction-handler---void)
- Deprecate `Promise.prototype.spawn`
Bugfixes:
- Fix already rejected promises being reported as unhandled when handled through collection methods
- Fix browserisfy crashing from checking `process.version.indexOf`
## 1.0.8 (2014-03-03)
Bugfixes:
- Fix active domain being lost across asynchronous boundaries in Node.JS 10.xx
## 1.0.7 (2014-02-25)
Bugfixes:
- Fix handled errors being reported
## 1.0.6 (2014-02-17)
Bugfixes:
- Fix bug with unhandled rejections not being reported
when using `Promise.try` or `Promise.method` without
attaching further handlers
## 1.0.5 (2014-02-15)
Features:
- Node.js performance: promisified functions try to check amount of passed arguments in most optimal order
- Node.js promisified functions will have same `.length` as the original function minus one (for the callback parameter)
## 1.0.4 (2014-02-09)
Features:
- Possibly unhandled rejection handler will always get a stack trace, even if the rejection or thrown error was not an error
- Unhandled rejections are tracked per promise, not per error. So if you create multiple branches from a single ancestor and that ancestor gets rejected, each branch with no error handler with the end will cause a possibly unhandled rejection handler invocation
Bugfixes:
- Fix unhandled non-writable objects or primitives not reported by possibly unhandled rejection handler
## 1.0.3 (2014-02-05)
Bugfixes:
- [#93](https://github.com/petkaantonov/bluebird/issues/88)
## 1.0.2 (2014-02-04)
Features:
- Significantly improve performance of foreign bluebird thenables
Bugfixes:
- [#88](https://github.com/petkaantonov/bluebird/issues/88)
## 1.0.1 (2014-01-28)
Features:
- Error objects that have property `.isAsync = true` will now be caught by `.error()`
Bugfixes:
- Fix TypeError and RangeError shims not working without `new` operator
## 1.0.0 (2014-01-12)
Features:
- `.filter`, `.map`, and `.reduce` no longer skip sparse array holes. This is a backwards incompatible change.
- Like `.map` and `.filter`, `.reduce` now allows returning promises and thenables from the iteration function.
Bugfixes:
- [#58](https://github.com/petkaantonov/bluebird/issues/58)
- [#61](https://github.com/petkaantonov/bluebird/issues/61)
- [#64](https://github.com/petkaantonov/bluebird/issues/64)
- [#60](https://github.com/petkaantonov/bluebird/issues/60)
## 0.11.6-1 (2013-12-29)
## 0.11.6-0 (2013-12-29)
Features:
- You may now return promises and thenables from the filterer function used in `Promise.filter` and `Promise.prototype.filter`.
- `.error()` now catches additional sources of rejections:
- Rejections originating from `Promise.reject`
- Rejections originating from thenables using
the `reject` callback
- Rejections originating from promisified callbacks
which use the `errback` argument
- Rejections originating from `new Promise` constructor
where the `reject` callback is called explicitly
- Rejections originating from `PromiseResolver` where
`.reject()` method is called explicitly
Bugfixes:
- Fix `captureStackTrace` being called when it was `null`
- Fix `Promise.map` not unwrapping thenables
## 0.11.5-1 (2013-12-15)
## 0.11.5-0 (2013-12-03)
Features:
- Improve performance of collection methods
- Improve performance of promise chains
## 0.11.4-1 (2013-12-02)
## 0.11.4-0 (2013-12-02)
Bugfixes:
- Fix `Promise.some` behavior with arguments like negative integers, 0...
- Fix stack traces of synchronously throwing promisified functions'
## 0.11.3-0 (2013-12-02)
Features:
- Improve performance of generators
Bugfixes:
- Fix critical bug with collection methods.
## 0.11.2-0 (2013-12-02)
Features:
- Improve performance of all collection methods
## 0.11.1-0 (2013-12-02)
Features:
- Improve overall performance.
- Improve performance of promisified functions.
- Improve performance of catch filters.
- Improve performance of .finally.
Bugfixes:
- Fix `.finally()` rejecting if passed non-function. It will now ignore non-functions like `.then`.
- Fix `.finally()` not converting thenables returned from the handler to promises.
- `.spread()` now rejects if the ultimate value given to it is not spreadable.
## 0.11.0-0 (2013-12-02)
Features:
- Improve overall performance when not using `.bind()` or cancellation.
- Promises are now not cancellable by default. This is backwards incompatible change - see [`.cancellable()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#cancellable---promise)
- [`Promise.delay`](https://github.com/petkaantonov/bluebird/blob/master/API.md#promisedelaydynamic-value-int-ms---promise)
- [`.delay()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#delayint-ms---promise)
- [`.timeout()`](https://github.com/petkaantonov/bluebird/blob/master/API.md#timeoutint-ms--string-message---promise)
## 0.10.14-0 (2013-12-01)
Bugfixes:
- Fix race condition when mixing 3rd party asynchrony.
## 0.10.13-1 (2013-11-30)
## 0.10.13-0 (2013-11-30)
Bugfixes:
- Fix another bug with progression.
## 0.10.12-0 (2013-11-30)
Bugfixes:
- Fix bug with progression.
## 0.10.11-4 (2013-11-29)
## 0.10.11-2 (2013-11-29)
Bugfixes:
- Fix `.race()` not propagating bound values.
## 0.10.11-1 (2013-11-29)
Features:
- Improve performance of `Promise.race`
## 0.10.11-0 (2013-11-29)
Bugfixes:
- Fixed `Promise.promisifyAll` invoking property accessors. Only data properties with function values are considered.
## 0.10.10-0 (2013-11-28)
Features:
- Disable long stack traces in browsers by default. Call `Promise.longStackTraces()` to enable them.
## 0.10.9-1 (2013-11-27)
Bugfixes:
- Fail early when `new Promise` is constructed incorrectly
## 0.10.9-0 (2013-11-27)
Bugfixes:
- Promise.props now takes a [thenable-for-collection](https://github.com/petkaantonov/bluebird/blob/f41edac61b7c421608ff439bb5a09b7cffeadcf9/test/mocha/props.js#L197-L217)
- All promise collection methods now reject when a promise-or-thenable-for-collection turns out not to give a collection
## 0.10.8-0 (2013-11-25)
Features:
- All static collection methods take thenable-for-collection
## 0.10.7-0 (2013-11-25)
Features:
- throw TypeError when thenable resolves with itself
- Make .race() and Promise.race() forever pending on empty collections
## 0.10.6-0 (2013-11-25)
Bugfixes:
- Promise.resolve and PromiseResolver.resolve follow thenables too.
## 0.10.5-0 (2013-11-24)
Bugfixes:
- Fix infinite loop when thenable resolves with itself
## 0.10.4-1 (2013-11-24)
Bugfixes:
- Fix a file missing from build. (Critical fix)
## 0.10.4-0 (2013-11-24)
Features:
- Remove dependency of es5-shim and es5-sham when using ES3.
## 0.10.3-0 (2013-11-24)
Features:
- Improve performance of `Promise.method`
## 0.10.2-1 (2013-11-24)
Features:
- Rename PromiseResolver#asCallback to PromiseResolver#callback
## 0.10.2-0 (2013-11-24)
Features:
- Remove memoization of thenables
## 0.10.1-0 (2013-11-21)
Features:
- Add methods `Promise.resolve()`, `Promise.reject()`, `Promise.defer()` and `.resolve()`.
## 0.10.0-1 (2013-11-17)
## 0.10.0-0 (2013-11-17)
Features:
- Implement `Promise.method()`
- Implement `.return()`
- Implement `.throw()`
Bugfixes:
- Fix promises being able to use themselves as resolution or follower value
## 0.9.11-1 (2013-11-14)
Features:
- Implicit `Promise.all()` when yielding an array from generators
## 0.9.11-0 (2013-11-13)
Bugfixes:
- Fix `.spread` not unwrapping thenables
## 0.9.10-2 (2013-11-13)
Features:
- Improve performance of promisified functions on V8
Bugfixes:
- Report unhandled rejections even when long stack traces are disabled
- Fix `.error()` showing up in stack traces
## 0.9.10-1 (2013-11-05)
Bugfixes:
- Catch filter method calls showing in stack traces
## 0.9.10-0 (2013-11-05)
Bugfixes:
- Support primitives in catch filters
## 0.9.9-0 (2013-11-05)
Features:
- Add `Promise.race()` and `.race()`
## 0.9.8-0 (2013-11-01)
Bugfixes:
- Fix bug with `Promise.try` not unwrapping returned promises and thenables
## 0.9.7-0 (2013-10-29)
Bugfixes:
- Fix bug with build files containing duplicated code for promise.js
## 0.9.6-0 (2013-10-28)
Features:
- Improve output of reporting unhandled non-errors
- Implement RejectionError wrapping and `.error()` method
## 0.9.5-0 (2013-10-27)
Features:
- Allow fresh copies of the library to be made
## 0.9.4-1 (2013-10-27)
## 0.9.4-0 (2013-10-27)
Bugfixes:
- Rollback non-working multiple fresh copies feature
## 0.9.3-0 (2013-10-27)
Features:
- Allow fresh copies of the library to be made
- Add more components to customized builds
## 0.9.2-1 (2013-10-25)
## 0.9.2-0 (2013-10-25)
Features:
- Allow custom builds
## 0.9.1-1 (2013-10-22)
Bugfixes:
- Fix unhandled rethrown exceptions not reported
## 0.9.1-0 (2013-10-22)
Features:
- Improve performance of `Promise.try`
- Extend `Promise.try` to accept arguments and ctx to make it more usable in promisification of synchronous functions.
## 0.9.0-0 (2013-10-18)
Features:
- Implement `.bind` and `Promise.bind`
Bugfixes:
- Fix `.some()` when argument is a pending promise that later resolves to an array
## 0.8.5-1 (2013-10-17)
Features:
- Enable process wide long stack traces through BLUEBIRD_DEBUG environment variable
## 0.8.5-0 (2013-10-16)
Features:
- Improve performance of all collection methods
Bugfixes:
- Fix .finally passing the value to handlers
- Remove kew from benchmarks due to bugs in the library breaking the benchmark
- Fix some bluebird library calls potentially appearing in stack traces
## 0.8.4-1 (2013-10-15)
Bugfixes:
- Fix .pending() call showing in long stack traces
## 0.8.4-0 (2013-10-15)
Bugfixes:
- Fix PromiseArray and its sub-classes swallowing possibly unhandled rejections
## 0.8.3-3 (2013-10-14)
Bugfixes:
- Fix AMD-declaration using named module.
## 0.8.3-2 (2013-10-14)
Features:
- The mortals that can handle it may now release Zalgo by `require("bluebird/zalgo");`
## 0.8.3-1 (2013-10-14)
Bugfixes:
- Fix memory leak when using the same promise to attach handlers over and over again
## 0.8.3-0 (2013-10-13)
Features:
- Add `Promise.props()` and `Promise.prototype.props()`. They work like `.all()` for object properties.
Bugfixes:
- Fix bug with .some returning garbage when sparse arrays have rejections
## 0.8.2-2 (2013-10-13)
Features:
- Improve performance of `.reduce()` when `initialValue` can be synchronously cast to a value
## 0.8.2-1 (2013-10-12)
Bugfixes:
- Fix .npmignore having irrelevant files
## 0.8.2-0 (2013-10-12)
Features:
- Improve performance of `.some()`
## 0.8.1-0 (2013-10-11)
Bugfixes:
- Remove uses of dynamic evaluation (`new Function`, `eval` etc) when strictly not necessary. Use feature detection to use static evaluation to avoid errors when dynamic evaluation is prohibited.
## 0.8.0-3 (2013-10-10)
Features:
- Add `.asCallback` property to `PromiseResolver`s
## 0.8.0-2 (2013-10-10)
## 0.8.0-1 (2013-10-09)
Features:
- Improve overall performance. Be able to sustain infinite recursion when using promises.
## 0.8.0-0 (2013-10-09)
Bugfixes:
- Fix stackoverflow error when function calls itself "synchronously" from a promise handler
## 0.7.12-2 (2013-10-09)
Bugfixes:
- Fix safari 6 not using `MutationObserver` as a scheduler
- Fix process exceptions interfering with internal queue flushing
## 0.7.12-1 (2013-10-09)
Bugfixes:
- Don't try to detect if generators are available to allow shims to be used
## 0.7.12-0 (2013-10-08)
Features:
- Promisification now consider all functions on the object and its prototype chain
- Individual promisifcation uses current `this` if no explicit receiver is given
- Give better stack traces when promisified callbacks throw or errback primitives such as strings by wrapping them in an `Error` object.
Bugfixes:
- Fix runtime APIs throwing synchronous errors
## 0.7.11-0 (2013-10-08)
Features:
- Deprecate `Promise.promisify(Object target)` in favor of `Promise.promisifyAll(Object target)` to avoid confusion with function objects
- Coroutines now throw error when a non-promise is `yielded`
## 0.7.10-1 (2013-10-05)
Features:
- Make tests pass Internet Explorer 8
## 0.7.10-0 (2013-10-05)
Features:
- Create browser tests
## 0.7.9-1 (2013-10-03)
Bugfixes:
- Fix promise cast bug when thenable fulfills using itself as the fulfillment value
## 0.7.9-0 (2013-10-03)
Features:
- More performance improvements when long stack traces are enabled
## 0.7.8-1 (2013-10-02)
Features:
- Performance improvements when long stack traces are enabled
## 0.7.8-0 (2013-10-02)
Bugfixes:
- Fix promisified methods not turning synchronous exceptions into rejections
## 0.7.7-1 (2013-10-02)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.7-0 (2013-10-01)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.6-0 (2013-09-29)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.5-0 (2013-09-28)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.4-1 (2013-09-28)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.4-0 (2013-09-28)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.3-1 (2013-09-28)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.3-0 (2013-09-27)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.2-0 (2013-09-27)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.1-5 (2013-09-26)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.1-4 (2013-09-25)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.1-3 (2013-09-25)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.1-2 (2013-09-24)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.1-1 (2013-09-24)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.1-0 (2013-09-24)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.0-1 (2013-09-23)
Features:
- feature
Bugfixes:
- bugfix
## 0.7.0-0 (2013-09-23)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.5-2 (2013-09-20)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.5-1 (2013-09-18)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.5-0 (2013-09-18)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.4-1 (2013-09-18)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.4-0 (2013-09-18)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.3-4 (2013-09-18)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.3-3 (2013-09-18)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.3-2 (2013-09-16)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.3-1 (2013-09-16)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.3-0 (2013-09-15)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.2-1 (2013-09-14)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.2-0 (2013-09-14)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.1-0 (2013-09-14)
Features:
- feature
Bugfixes:
- bugfix
## 0.6.0-0 (2013-09-13)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-6 (2013-09-12)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-5 (2013-09-12)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-4 (2013-09-12)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-3 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-2 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-1 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.9-0 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.8-1 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.8-0 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.7-0 (2013-09-11)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.6-1 (2013-09-10)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.6-0 (2013-09-10)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.5-1 (2013-09-10)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.5-0 (2013-09-09)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.4-1 (2013-09-08)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.4-0 (2013-09-08)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.3-0 (2013-09-07)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.2-0 (2013-09-07)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.1-0 (2013-09-07)
Features:
- feature
Bugfixes:
- bugfix
## 0.5.0-0 (2013-09-07)
Features:
- feature
Bugfixes:
- bugfix
## 0.4.0-0 (2013-09-06)
Features:
- feature
Bugfixes:
- bugfix
## 0.3.0-1 (2013-09-06)
Features:
- feature
Bugfixes:
- bugfix
## 0.3.0 (2013-09-06)
================================================
FILE: docs/docs/coming-from-other-languages.md
================================================
---
id: coming-from-other-languages
title: Coming from Other Languages
---
This page describes parallels of using promises in other languages. Promises as a pattern are very common in other languages and knowing what they map to in other languages might help you with grasping them conceptually
- [C#](#c)
- [Scala](#scala)
- [Python](#python)
- [C++](#c)
- [Haskell](#haskell)
- [Java](#java)
- [Android Java](#android-java)
- [Objective-C](#objective-c)
## C#
A promise is similar to a C# `Task`. They both represent the result of an operation.
A promise's `then` method is similar to a Task's `ContinueWith` method in that both allow attaching a continuation to the promise. Bluebird's [Promise.coroutine](.) is analogous to C#'s `async/await` syntax.
A `TaskCompletionSource` is analogous to the promise constructor. Although usually promisification is preferred (see the API reference or working with callbacks section).
`Task.FromResult` is analogous to [Promise.resolve](.).
The difference between a `Task` and a promise are that a task might not be started and might require a `.Start` call where a promise always represents an already started operation.
In addition promises are always unwrapped. A promise implicitly has `Task.Unwrap` called on it - that is, promises perform recursive assimilation of promises within them.
See [this question on StackOverflow](http://stackoverflow.com/questions/26136389/how-can-i-realize-pattern-promise-deffered) for more differences.
## Scala
A bluebird promise is similar to a Scala `Future`. A scala `Promise` is similar to how the promise constructor can be used (previously, to a bluebird Deferred).
Just like a future, a promise represents a value over time. The value can resolve to either a fulfilled (ok completion) or rejected (error completion) state.
Where blocking on a Future in scala is discouraged, in JavaScript it's downright impossible.
In addition promises are always unwrapped. That is, promises perform recursive assimilation of promises within them. You can't have a `Promise>` where a `Future[Future[T]]` is valid in Scala.
See [this question on StackOverflow](http://stackoverflow.com/questions/22724883/js-deferred-promise-future-compared-to-functional-languages-like-scala) for more differences.
## Python
A promise is similar to a Twisted Deferred object. In fact the first JavaScript implementations of promises were based on it. However, the APIs have diverged since. The mental model is still very similar.
A promise is _not_ similar to a Python `concurrent.Future` which does not chain actions.
Asyncio coroutines are similar to bluebird coroutines in what they let you do, however bluebird coroutines also enable functional-style chaining.
## C++
A bluebird promise is similar to a `std::future` and the promise constructor is similar to an `std::promise` although it should rarely be used in practice (see the promisification section).
However, a bluebird promise is more powerful than the current implementation of `std::future` since while chaining has been discussed it is not yet implemented. Promises can be chained together.
Boost futures expose a `.then` method similar to promises and allow this functionality.
## Haskell
A promise is a monadic construct with `.then` filling the role of `>>=` (bind). The major difference is that `.then` performs recursive assimilation which acts like a `flatMap` or a map. The type signature of `then` is quote complicated. If we omit the error argument and not throw - it's similar to:
```hs
then::Promise a -> (a -> (Either (Promise b) b)) -> Promise b
```
That is, you can return either a promise _or a plain value_ from a `then` without wrapping it.
Promises perform a role similar to `IO` in that they allow for easy chaining of asynchronous non-blocking operations. `Promise.coroutine` can be seen as similar to `do` notation although in practice it's not an accurate comparison.
## Java
A promise is similar to a guava `Future` with `chain` being similar to `then`.
If your'e familiar with Java 8 lambdas, you can think of a promise as a `Future` you can `map` to another future.
## Android Java
Several popular Android libraries use promises - for example the Parse Java API returns `Task`s which are similar to JavaScript promises.
## Objective-C
If you're familiar with PromiseKit, it is based on a same specification bluebird is based on so the API should feel familiar right away.
================================================
FILE: docs/docs/coming-from-other-libraries.md
================================================
---
id: coming-from-other-libraries
title: Coming from Other Libraries
---
This page is a reference for migrating to bluebird from other flow control or promise libraries. See [installation](install.html) on how to use bluebird in your environment.
- [Coming from native promises](#coming-from-native-promises)
- [Coming from jQuery deferreds](#coming-from-jquery-deferreds)
- [Coming from `async` module](#coming-from-async-module)
- [Coming from Q](#coming-from-q)
- [Coming from co/koa](#coming-from-co)
- [Coming from highland, RxJS or BaconJS](#coming-from-highland)
##Coming from native promises
Bluebird promises are a drop-in replacement for native promises except for subclassing. Additionally you might want to replace usages of the often incorrectly used [Promise.race](.) with bluebird's [Promise.any](.) which does what is usually mistakenly expected from [Promise.race](.). For maximum compatibility, bluebird does provide [Promise.race](.) with ES6 semantics.
You can also refactor some looping patterns to a more natural form that would [leak memory when using native promises](https://github.com/promises-aplus/promises-spec/issues/179).
##Coming from jQuery deferreds
Bluebird treats jQuery deferreds and promises interchangeably. Wherever you can take a promise or return a promise, you can take or return a jQuery deferred instead and it works the same.
For instance, there is no need to write something like this:
```js
var firstRequest = new Promise(function(resolve, reject) {
$.ajax({...}).done(resolve).fail(reject);
});
var secondRequest = new Promise(function(resolve, reject) {
$.ajax({...}).done(resolve).fail(reject);
});
Promise.all([firstRequest, secondRequest]).then(function() {
// ...
});
```
Since [Promise.all](.) takes promises, it must also take jQuery deferreds, so the above can be shortened to:
```js
var firstRequest = $.ajax({...});
var secondRequest = $.ajax({...});
Promise.all([firstRequest, secondRequest]).then(function() {
// ...
});
```
That said, if you have code written using jQuery deferred methods, such as `.then`, `.done` and so on, you cannot drop-in replace the jQuery deferred with a bluebird promise in that code. Despite having the same names, jQuery deferred methods have different semantics than bluebird promise methods. These differences are due to the completely different goals of the implementations. Bluebird is [an internal DSL](http://en.wikipedia.org/wiki/Domain-specific_language) for the domain of asynchronous control flow while jQuery deferreds are a callback aggregator utility ("glorified event emitters").
If you do have some code using jQuery deferred methods extensively try to see if some of these jQuery deferred patterns and their replacements can be applied:
```js
// jQuery
$.when.apply($, someArray).then(...)
// bluebird
Promise.all(someArray).then(...)
```
```js
// jQuery
var data = [1,2,3,4];
var processItemsDeferred = [];
for(var i = 0; i < data.length; i++) {
processItemsDeferred.push(processItem(data[i]));
}
$.when.apply($, processItemsDeferred).then(everythingDone);
// bluebird
var data = [1,2,3,4];
Promise.map(data, function(item) {
return processItem(item);
}).then(everythingDone);
```
```js
// jQuery
var d = $.Deferred();
d.resolve("value");
// bluebird
var d = Promise.resolve("value");
```
```js
// jQuery
var d = $.Deferred();
d.reject(new Error("error"));
// bluebird
var d = Promise.reject(new Error("error"));
```
```js
// jQuery
var clicked = $.Deferred();
$("body").one("click", function(e) {
clicked.resolve(e);
});
// bluebird
var clicked = new Promise(function(resolve) {
$("body").one("click", resolve);
});
```
```js
// jQuery
.always(removeSpinner);
// bluebird
.finally(removeSpinner);
```
##Coming from `async` module
When working with promises the philosophy is basically a complete opposite than when using `async`. Async provides a huge bag of uncomposable helper functions that work at a very low level of abstraction. When using promises you can get the utility otherwise provided by uncountable amount of inflexible helper functions by just combining and composing a few existing functions and concepts.
That means when you have a problem there probably isn't an existing function tailored exactly to that problem but instead you can just combine the existing utilities to arrive at a solution. The upside of this is that you don't need to come up with all these different functions to solve problems that are not that different from each other. The most important thing to do when migrating from async to bluebird is this profound shift in philosophy.
This section lists the most common async module replacements.
###`async.waterfall`
If the waterfall elements are static, you can just replace it with a normal promise chain. For waterfalls with dynamic steps, use [Promise.each](.). Multiple arguments can be ferried in an array.
Implementing the example from [async homepage](https://github.com/caolan/async#waterfalltasks-callback)
```js
async.waterfall([
function(callback) {
callback(null, 'one', 'two');
},
function(arg1, arg2, callback) {
// arg1 now equals 'one' and arg2 now equals 'two'
callback(null, 'three');
},
function(arg1, callback) {
// arg1 now equals 'three'
callback(null, 'done');
}
], function (err, result) {
// result now equals 'done'
});
```
Since the array passed to waterfall is static (always the same 3 functions) a plain old promise chain is used:
```js
Promise.resolve(['one', 'two']).spread(function(arg1, arg2) {
// arg1 now equals 'one' and arg2 now equals 'two'
return 'three';
}).then(function(arg1) {
// arg1 now equals 'three'
return 'done';
}).then(function(result) {
// result now equals 'done'
});
```
If destructuring parameters are supported, `.spread(function(arg1, arg2) {})` can be replaced with `.then(function([arg1, arg2]){})`.
###`async.series`
Using [Promise.mapSeries](.) to implement the example from [async homepage](https://github.com/caolan/async#seriestasks-callback):
```js
async.series([
function(callback){
setTimeout(function(){
callback(null, 1);
}, 200);
},
function(callback){
setTimeout(function(){
callback(null, 2);
}, 100);
}
],
// optional callback
function(err, results){
// results is now equal to [1, 2]
});
```
```js
Promise.mapSeries([{timeout: 200, value: 1},
{timeout: 100, value: 2}], function(item) {
return Promise.delay(item.timeout, item.value);
}).then(function(results) {
// results is now equal to [1, 2]
});
```
###`async.parallel`
Using [Promise.all](.) to implement the example from [async homepage](https://github.com/caolan/async#parallel):
```js
async.parallel([
function(callback){
setTimeout(function(){
callback(null, 'one');
}, 200);
},
function(callback){
setTimeout(function(){
callback(null, 'two');
}, 100);
}
],
// optional callback
function(err, results){
// the results array will equal ['one','two'] even though
// the second function had a shorter timeout.
});
```
```js
Promise.all([Promise.delay(200, 'one'),
Promise.delay(100, 'two')]).then(function(results) {
// the results array will equal ['one','two'] even though
// the second function had a shorter timeout.
});
```
###`async.mapSeries`
Using [Promise.each](.) to implement the example from [async homepage](https://github.com/caolan/async#maparr-iterator-callback):
```js
var fs = require('fs');
async.mapSeries(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
```
```js
var fs = Promise.promisifyAll(require('fs'));
Promise.each(['file1','file2','file3'], function(fileName, index, length) {
return fs.statAsync(fileName);
}).then(function(results) {
// results is now an array of stats for each file
});
```
###`async.map`
Using [Promise.map](.) to implement the example from [async homepage](https://github.com/caolan/async#maparr-iterator-callback):
```js
var fs = require('fs');
async.map(['file1','file2','file3'], fs.stat, function(err, results){
// results is now an array of stats for each file
});
```
```js
var fs = Promise.promisifyAll(require('fs'));
Promise.map(['file1','file2','file3'], function(fileName, index, length) {
return fs.statAsync(fileName);
}).then(function(results) {
// results is now an array of stats for each file
});
```
###`async.whilst`
Using recursion to implement the example from [async homepage](https://github.com/caolan/async#whilsttest-fn-callback):
```js
var count = 0;
async.whilst(
function () { return count < 5; },
function (callback) {
count++;
setTimeout(callback, 1000);
},
function (err) {
// 5 seconds have passed
}
);
```
```js
(function loop() {
if (count < 5) {
count++;
return Promise.delay(1000).then(loop);
}
return Promise.resolve();
})().then(function() {
// 5 seconds have passed
});
```
Be warned that the above example implementations are only superficially equivalent. Callbacks, even with the help of async, require too much boilerplate code to provide the same guarantees as promises.
##Coming from Q
Q and bluebird share a lot of common methods that nevertheless have different names:
- `Q(...)` -> [Promise.resolve()](.)
- `.fail()` -> [.catch()](.) or `.caught()`
- `.fin()` -> [.finally()](.) or `.lastly()`
- `Q.fcall()` -> [Promise.try](.) or `Promise.attempt()`
- `.thenResolve()` -> [.return()](.) or `.thenReturn()`
- `.thenReject()` -> [.throw()](.) or `thenThrow()`
##Coming from co/koa
In recent versions generator libraries started abandoning old ideas of special tokens passed to callbacks and started using promises for what's being yielded.
Bluebird's [Promise.coroutine](.) is a superset of the `co` library, being more extensible as well as supporting cancellation (in environments where [`Generator#return`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) is implemented).
##Coming from highland, RxJS or BaconJS
Stream libraries tend to serve a different purpose than promise libraries. Unlike promise libraries streams can represent multiple values.
Check out the benchmarks section for examples of transitioning an API from Bacon/Rx to promises.
================================================
FILE: docs/docs/contribute.md
================================================
---
id: contribute
title: Contribute
---
For development tasks such as contributing, running benchmarks or testing, you need to clone the repository and install dev-dependencies.
Install [node](http://nodejs.org/)
git clone git@github.com:petkaantonov/bluebird.git
cd bluebird
npm install
- [Directory structure](#directory-structure)
- [Style guide](#style-guide)
- [Building](#building)
- [Supported options by the build tool](#supported-options-by-the-build-tool)
- [Testing](#testing)
- [Testing in browsers](#testing-in-browsers)
- [Supported options by the test tool](#supported-options-by-the-test-tool)
- [Benchmarking](#benchmarking)
## Directory structure
- `/benchmark` contains benchmark scripts and stats of benchmarks
- `/tools` contains building and testing tools and scripts
- `/src` contains the source code
- `/test` contains test code
- `/test/mocha` contains tests using the mocha testing framework
- `/test/browser` a directory that can be statically served using a webserver to run tests in browsers. See [testing in browsers](README.md#testing-in-browsers).
## Style guide
Use the same style as is used in the surrounding code.
###Whitespace
- No more than 80 columns per line
- 4 space indentation
- No trailing whitespace
- LF at end of files
- Curly braces can be left out of single statement `if/else/else if`s when it is obvious there will never be multiple statements such as null check at the top of a function for an early return.
- Add an additional new line between logical sections of code.
###Variables
- Use multiple `var` statements instead of a single one with comma separator. Do not declare variables until you need them.
###Equality and type checks
- Always use `===` except when checking for null or undefined. To check for null or undefined, use `x == null`.
- For checks that can be done with `typeof`: do not make helper functions, save results of `typeof` to a variable or make the type string a non-constant. Always write the check in the form `typeof expression === "constant string"` even if it feels like repeating yourself.
##Building
```
node tools/build --debug --release --zalgo --browser --minify
```
###Supported options by the build tool
The value of boolean flags is determined by presence, if you want to pass false value for a boolean flag, use the `no-`-prefix e.g. `--no-debug`.
- `--release` - Whether to build the release build. The release build is placed at `js/release` directory. Default `false`.
- `--debug` - Whether to build the debug build. The debug build is placed at `js/debug` directory. Default `false`.
- `--zalgo` - Whether to build the zalgo build. The zalgo build is placed at `js/zalgo` directory. Default `false`.
- `--browser` - Whether to compile the browser build. The browser build file is placed at `js/browser/bluebird.js` Default `false`.
- `--minify` - Whether to minify the compiled browser build. The minified browser build file is placed at `js/browser/bluebird.min.js` Default `true`.
##Testing
To run all tests, run
node --expose-gc tools/test
If you need to run generator tests in older versions of NodeJS run the `tool/test.js` script with `--harmony` argument and 0.11+:
node-dev --harmony tools/test
In recent versions of NodeJS where generators are enabled by default:
node tools/test
You may specify an individual test file to run with the `--run` script flag:
node tools/test --run=cancel.js
This enables output from the test and may give a better idea where the test is failing. The paramter to `--run` can be any file name located in `test/mocha` folder.
###Testing in browsers
To run the test in a browser instead of node, pass the flag `--browser` to the test tool
node tools/test --run=cancel.js --browser
This will automatically create a server (default port 9999) and open it in your default browser once the tests have been compiled.
Keep the test tab active because some tests are timing-sensitive and will fail if the browser is throttling timeouts. Chrome will do this for example when the tab is not active.
###Supported options by the test tool
The value of boolean flags is determined by presence, if you want to pass false value for a boolean flag, use the `no-`-prefix e.g. `--no-browser`.
- `--run=String`. Which tests to run (or compile when testing in browser). Default `"all"`. Can also be a glob string (relative to ./test/mocha folder)
- `--cover=String`. Create code coverage using the String as istanbul reporter. Coverage is created in the ./coverage folder. No coverage is created by default, default reporter is `"html"` (use `--cover` to use default reporter).
- `--browser` - Whether to compile tests for browsers. Default `false`.
- `--port=Number` - Whe port where local server is hosted when testing in browser. Default `9999`
- `--execute-browser-tests` - Whether to execute the compiled tests for browser when using `--browser`. Default `true`.
- `--open-browser` - Whether to open the default browser when executing browser tests. Default `true`.
- `--fake-timers` - Whether to use fake timers (`setTimeout` etc) when running tests in node. Default `true`.
- `--js-hint` - Whether to run JSHint on source files. Default `true`.
- `--saucelabs` Wheter to create a tunnel to sauce labs and run tests in their VMs instead of your browser when compiling tests for browser.Default `false`.
##Benchmarking
To run a benchmark, run the given command for a benchmark while on the project root. Requires bash (on windows the mingw32 that comes with git works fine too).
Each benchmark must
- Have implementations that do the same thing
- Run each implementation of a benchmark in a separate freshly created process
- Warmup each implementation before timing
###1\. DoxBee sequential
Currently the most relevant benchmark is @gorkikosev's benchmark in the article [Analysis of generators and other async patterns in node](http://spion.github.io/posts/analysis-generators-and-other-async-patterns-node.html). The benchmark emulates a situation where n amount of users are making a request in parallel to execute some mixed async/sync action.
Command: `bench doxbee`
The implementations for this benchmark are found in `benchmark/doxbee-sequential` directory.
###2\. Parallel
This made-up scenario runs 25 shimmed queries in parallel.
Command: `bench parallel`
The implementations for this benchmark are found in `benchmark/madeup-parallel` directory.
================================================
FILE: docs/docs/deprecated-apis.md
================================================
---
id: deprecated-apis
title: Deprecated APIs
---
[deprecated-apis](unfinished-article)
This file contains documentation for APIs that are no longer supported by Bluebird.
These APIs still work in Bluebird but will be removed at a future version of the library.
For every use case that the methods below solve there exists a better alternative in [the API reference](/docs/api-reference.html).
- [Progression](#progression)
- [`.progressed(Function handler)`](#progressedfunction-handler---promise)
- [`.then([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])`](#thenfunction-fulfilledhandler--function-rejectedhandler---function-progresshandler----promise)
- [`.done([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])`](#donefunction-fulfilledhandler--function-rejectedhandler---function-progresshandler----promise)
- [Promise resolution](#promise-resolution)
- [`.resolve(dynamic value)`](#resolvedynamic-value---undefined)
- [`.reject(dynamic reason)`](#rejectdynamic-reason---undefined)
- [`.progress(dynamic value)`](#progressdynamic-value---undefined)
- [`.callback`](#callback---function)
- [Old Promise Cancellation](#old-promise-cancellation)
##Progression
The old progression API was meant to be used for tracking the progress of promise resolution. In retrospect, it did not work or compose very well. We understand that problem better now and the use case could be better solved without it.
See [Progression Migration](./api/progression-migration.html) for migration assistance and examples of how to convert APIs that use progression to ones that do not.
#####`.progressed(Function handler)` -> `Promise`
Shorthand for `.then(null, null, handler);`. Attach a progress handler that will be called if this promise is progressed. Returns a new promise chained from this promise.
#####`.then([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])` -> `Promise`
The standard [Promises/A+ `.then()`](http://promises-aplus.github.io/promises-spec/) is still supported by Bluebird and support for it will continue indefinitely . However, the variant accepting a third `progressHandler` argument is no longer supported.
#####`.done([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])` -> `void`
Like `.then()`, but any unhandled rejection that ends up here will be thrown as an error. Again, only the variant with the progression handler is deprecated here. `.done` is still fully supported.
##Promise resolution
A `PromiseResolver` can be used to control the fate of a promise. It is like "Deferred" in jQuery or `$q.defer` in $q. The `PromiseResolver` objects have a `.promise` property which returns a reference to the controlled promise that can be passed to clients. `.promise` of a `PromiseResolver` is not a getter function to match other implementations.
The methods of a `PromiseResolver` have no effect if the fate of the underlying promise is already decided (follow, reject, fulfill).
**The use of `Promise.defer` and deferred objects is discouraged - it is much more awkward and error-prone than using `new Promise`.**
#####`.resolve(dynamic value)` -> `undefined`
Resolve the underlying promise with `value` as the resolution value. If `value` is a thenable or a promise, the underlying promise will assume its state.
#####`.reject(dynamic reason)` -> `undefined`
Reject the underlying promise with `reason` as the rejection reason.
#####`.progress(dynamic value)` -> `undefined`
Progress the underlying promise with `value` as the progression value.
Example
```js
function delay(ms) {
var resolver = Promise.defer();
var now = Date.now();
setTimeout(function(){
resolver.resolve(Date.now() - now);
}, ms);
return resolver.promise;
}
delay(500).then(function(ms){
console.log(ms + " ms passed");
});
```
##Old Promise Cancellation
In 2.x, promise cancellation looked very differently. Promise cancellation received a major overhaul for version 3 in order to create a sound variant of cancellable promises. You can still use 2.x cancellation with bluebird 2.x (which is still supported - but not recommended). See [Cancellation](/cancellation.html) for more details. The 2.x docs are [still accessible under the 2.x branch](https://github.com/petkaantonov/bluebird/blob/2.x/API.md).
================================================
FILE: docs/docs/deprecated_apis.md
================================================
---
id: deprecated_apis
title: Deprecated APIs
---
This file contains documentation for APIs that are no longer supported by Bluebird.
These APIs still work in Bluebird but will be removed at a future version of the library.
For every use case that the methods below solve there exists a better alternative in [the API reference](./API.md).
- [Progression](#progression)
- [`.progressed(Function handler)`](#.progressed)
- [`.then([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])`](#.then)
- [`.done([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])`](#.done)
- [`.fork([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])`](#.fork)
- [Promise resolution](#promise-resolution)
- [`.resolve(dynamic value)`](#.resolve)
- [`.reject(dynamic reason)`](#.reject)
- [`.progress(dynamic value)`](#.progress)
- [`.callback`](#.callback)
##Progression
The old progression API was meant to be used for tracking the progress of promise resolution. In retrospect, it did not work or compose very well. We understand that problem better now and the use case could be better solved without it.
See [Progression Migration](./API.md#progression-migration) for migration assistance and examples of how to convert APIs that use progression to ones that do not.
#####`.progressed(Function handler)` -> `Promise`
Shorthand for [`.then(null, null, handler);`](.). Attach a progress handler that will be called if this promise is progressed. Returns a new promise chained from this promise.
#####`.then([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])` -> `Promise`
The standard [Promises/A+ `.then()`](http://promises-aplus.github.io/promises-spec/) is still supported by Bluebird and support for it will continue indefinitely. However, the variant accepting a third `progressHandler` argument is no longer supported.
#####`.done([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])` -> `void`
Like [`.then()`](.), but any unhandled rejection that ends up here will be thrown as an error. Again, only the variant with the progression handler is deprecated here. `.done` is still fully supported.
#####`.fork([Function fulfilledHandler] [, Function rejectedHandler ] [, Function progressHandler ])` -> `Promise`
Like [`.then()`](.), but cancellation of the returned promise or any of its descendant will not propagate cancellation to this promise or this promise's ancestors. Again, only the variant with the progression handler is deprecated here. `.fork` is still fully supported.
##Promise resolution
A `PromiseResolver` can be used to control the fate of a promise. It is like "Deferred" in jQuery or `$q.defer` in $q. The `PromiseResolver` objects have a `.promise` property which is a reference to the controlled promise that can be passed to clients. `.promise` of a `PromiseResolver` is not a getter function to match other implementations.
The methods of a `PromiseResolver` have no effect if the fate of the underlying promise is already decided (follow, reject, fulfill).
**The use of `Promise.defer` and deferred objects is discouraged - it is much more awkward and error-prone than using `new Promise`.**
#####`.resolve(dynamic value)` -> `undefined`
Resolve the underlying promise with `value` as the resolution value. If `value` is a thenable or a promise, the underlying promise will assume its state.
#####`.reject(dynamic reason)` -> `undefined`
Reject the underlying promise with `reason` as the rejection reason.
#####`.progress(dynamic value)` -> `undefined`
Progress the underlying promise with `value` as the progression value.
Example
```js
function delay(ms) {
var resolver = Promise.defer();
var now = Date.now();
setTimeout(function() {
resolver.resolve(Date.now() - now);
}, ms);
return resolver.promise;
}
delay(500).then(function(ms) {
console.log(ms + " ms passed");
});
```
================================================
FILE: docs/docs/download-api-reference.md
================================================
---
id: download-api-reference
title: Download API Reference
---
In order to use the documentation offline (without a stable internet connection).
- Go to [the GitHub Pages Branch `gh-pages`](https://github.com/petkaantonov/bluebird/tree/gh-pages).
- Click "Clone Or Download".
- Click "Download Zip".
- Extract the contents of the zip and open the "docs" folder.
- Open `api-reference.html` which is the documentation root.
================================================
FILE: docs/docs/error-explanations.md
================================================
---
id: error-explanations
title: Error Explanations
---
- [Error: Promise.promisify called on an object](#error-promise.promisify-called-on-an-object)
- [Error: the promise constructor requires a resolver function](#error-the-promise-constructor-requires-a-resolver-function)
- [Error: the promise constructor cannot be invoked directly](#error-the-promise-constructor-cannot-be-invoked-directly)
- [Error: expecting an array, a promise or a thenable](#error-expecting-an-array-a-promise-or-a-thenable)
- [Error: generatorFunction must be a function](#error-generatorfunction-must-be-a-function)
- [Error: fn must be a function](#error-fn-must-be-a-function)
- [Error: cannot enable long stack traces after promises have been created](#error-cannot-enable-long-stack-traces-after-promises-have-been-created)
- [Error: cannot get fulfillment value of a non-fulfilled promise](#error-cannot-get-fulfillment-value-of-a-non-fulfilled-promise)
- [Error: cannot get rejection reason of a non-rejected promise](#error-cannot-get-rejection-reason-of-a-non-rejected-promise)
- [Error: the target of promisifyAll must be an object or a function](#error-the-target-of-promisifyall-must-be-an-object-or-a-function)
- [Error: circular promise resolution chain](#error-circular-promise-resolution-chain)
- [Error: cannot await properties of a non-object](#error-cannot-await-properties-of-a-non-object)
- [Error: expecting a positive integer](#error-expecting-a-positive-integer)
- [Error: A value was yielded that could not be treated as a promise](#error-a-value-was-yielded-that-could-not-be-treated-as-a-promise)
- [Error: cannot await properties of a non object](#error-cannot-await-properties-of-a-non-object)
- [Error: Cannot promisify an API that has normal methods](#error-cannot-promisify-an-api-that-has-normal-methods)
- [Error: Catch filter must inherit from Error or be a simple predicate function](#error-catch-filter-must-inherit-from-error-or-be-a-simple-predicate-function)
- [Error: No async scheduler available](#error-no-async-scheduler-available)
## Error: Promise.promisify called on an object
You got this this error because you've used `Promise.promisify` on an object, for example:
```js
var fs = Promise.promisify(require("fs"));
```
Instead, use [`Promise.promisifyAll`](.) :
```js
var fs = Promise.promisifyAll(require("fs"));
```
## Error: the promise constructor requires a resolver function
You got this error because you used `new Promise()` or `new Promise(something)` without passing a function as the parameter.
If you want to wrap an API with a promise manually, the correct syntax is:
```js
function wrapWithPromise(parameter) {
return new Promise(function (resolve, reject) {
doSomethingAsync({
error:reject,
success:resolve
});
});
}
```
Please consider reading about [new Promise](.) and also consider checking out automatic [promisification](.) as well as [Promise.method](.)
## Error: the promise constructor cannot be invoked directly
You can get this error for several reasons:
#### 1. You forgot to use `new` when creating a new promise using `new Promise(resolver)` syntax.
This can happen when you tried to do something like:
return Promise(function(resolve,reject){
//...
})
You can correct this by doing:
return new Promise(function(resolve,reject){
//...
})
Please consider reading about [new Promise](.) and also consider checking out automatic [promisification](.) as well as [Promise.method](.)
#### 2. You are trying to subclass `Promise`
Bluebird does not support extending promises this way. Instead, see [scoped prototypes](features.html#scoped-prototypes).
## Error: expecting an array, a promise or a thenable
The function being called expects a Promise, but is given something different. There are two main reasons why this may occur.
**1. Working with collections (like arrays) but pass a single, non-collection element instead**
Example:
```js
function returnThree(){ return 3;}
Promise.resolve(5).map(returnThree).then(function(val){
console.log("Hello Value!",val);
});
```
The `map` operation is expecting an array here (or a promise on one) and instead gets the number `5`.
```js
function returnThree(){ return 3;}
Promise.resolve([5]).map(returnThree).then(function(val){
console.log("Hello Value!",val);
});
```
```map``` is given an array with a single element (see ```[5]``` instead of ```5```), so this statement will work (but is bad practice).
---
**2.```return``` is forgotten in a 'fat' arrow / anonymous function call ```=>```:**
When debugging or performing a one-time operation on a variable before passing it to a function, a return variable is forgotten.
Example:
```js
function nextFunction(something){ return Promise.resolve(something*3); }
myFunction()
.then(result => nextFunction(result)); // We are implicitly returning a Promise
```
Debugging, we want to see the value of result, so we add a ```console.log()``` line:
```js
function nextFunction(something){ return Promise.resolve(something*3); }
myFunction().then(result => {
console.log("Debug:", result);
nextFunction(result)); // The chain is broken! We don't return anything to the .then() call
});
```
As this is an anonymous function call, we need to **return** something, which is not currently happening.
To fix, simply remember to add ```return``` in front of your promise-complying function:
```js
function nextFunction(something){ return Promise.resolve(something*3); }
myFunction().then(result => {
console.log("Debug:", result);
return nextFunction(result)); // The anonymous function returns the function which returns the promise .then() needs
});
```
## Error: generatorFunction must be a function
You are getting this error when trying to use [Promise.coroutine](.) and not passing it a generator function as a parameter. For example:
```js
Promise.coroutine(function* () { // Note the *
var data = yield $.get("http://www.example.com");
var moreUrls = data.split("\n");
var contents = [];
for( var i = 0, len = moreUrls.length; i < len; ++i ) {
contents.push(yield $.get(moreUrls[i]));
}
return contents;
});
```
Please refer to the relevant section in the documentation about [Generators](.) in order to get usage instructions:
**Note**: Bluebird used to eagerly check for generators which caused problems with transpilers. Because of this, you might get an error similar to `TypeError: Cannot read property 'next' of undefined` if you pass a function instead of a generator function to Bluebird.
[Promise.coroutine](.) is built to work with generators to form C# like `async/await`
## Error: fn must be a function
You passed a non-function where a function was expected.
## Error: cannot enable long stack traces after promises have been created
You are getting this error because you are enabling long stack traces after a promise has already been created.
When using `longStackTraces` the first line in your code after requiring Bluebird should be:
```js
Promise.config({
longStackTraces: true
});
```
See the API page about [Promise.longStackTraces](.)
## Error: cannot get fulfillment value of a non-fulfilled promise
You can get this error when you're trying to call `.value` or `.error` when inspecting a promise where the promise has not been fulfilled or rejected yet.
For example:
```js
var p = Promise.delay(1000);
p.inspect().value();
```
Consider using [.isPending()](.) [.isFulfilled()](.) and [.isRejected()](.) in order to inspect the promise for status.
Please consider reading more about [synchronous inspection](.)
## Error: cannot get rejection reason of a non-rejected promise
You can get this error when you're trying to call `.value` or `.error` when inspecting a promise where the promise has not been fulfilled or rejected yet.
For example:
```js
var p = Promise.delay(1000);
p.inspect().value();
```
Consider using [.isPending()](.) [.isFulfilled()](.) and [.isRejected()](.) in order to inspect the promise for status.
Please consider reading more about [synchronous inspection](.)
##Error: the target of promisifyAll must be an object or a function
This can happen when you are calling [Promise.promisifyAll](.) on a function and invoking it instead of passing it.
In general, the usage of [Promise.promisifyAll](.) is along the lines of `var fs = Promise.promisifyAll(require("fs"))`.
Consider reading the section about [promisification](.)
## Error: circular promise resolution chain
This usually happens when you have a promise that resolves or rejects with itself.
For example: `var p = Promise.delay(100).then(function(){ return p});` .
In this case, the promise resolves with itself which was is not intended.
This also happens when implementing live-updating models with a `.then` method that indicates when the model is "ready". A promise is a process, it starts and it ends.
Promises do not aim to solve such live updating problems directly. One option would be to use an intermediate promise - for example a `.loaded` property on the model that fulfills with nothing.
resolving it with itself tells it "it is done when it is done"
## Error: cannot await properties of a non-object
The `.props` method expects to receive an object.
For example:
```js
Promise.props({
pictures: getPictures(),
comments: getComments(),
tweets: getTweets()
}).then(function(result){
console.log(result.tweets, result.pictures, result.comments);
});
```
This happens when a non object value or a promise that resolves with something that is not an object is being passed instead.
## Error: expecting a positive integer
This happens when you call `.some` passing it a negative value or a non-integer.
One possible cause is using `.indexOf` which returns `-1` when it doesn't find the value being searched for.
Please consider reading the API docs for [`.some`](.)
## Error: A value was yielded that could not be treated as a promise
You are getting this error because you have tried to `yield` something in a coroutine without a yield handler, for example:
```js
var coroutine = Promise.coroutine(function*(){
var bar = yield "Foo";
console.log(bar);
});
```
The solution is to either convert it to a promise by calling `Promise.resolve` on it or `Promise.promisify` if it's a callback:
```js
var coroutine = Promise.coroutine(function*(){
var bar = yield Promise.resolve("Foo");
console.log(bar);
});
```
Or to use [Promise.coroutine.addYieldHandler`](.) to teach [Promise.coroutine](.) to accept these sort of values.
## Error: cannot await properties of a non object
The `.props` method expects to receive an object.
For example:
```js
Promise.props({
pictures: getPictures(),
comments: getComments(),
tweets: getTweets()
}).then(function(result){
console.log(result.tweets, result.pictures, result.comments);
});
```
This happens when a non object value or a promise that resolves with something that is not an object is being passed instead.
## Error: Cannot promisify an API that has normal methods
This error indicates you have tried to call [Promise.promisifyAll](.) on an object that already has a property with the `Async` suffix:
```js
var myApi = { foo: function(cb){ ... }, fooAsync(cb) { ... }
```
This is because Bluebird adds the `Async` suffix to distinguish the original method from the promisified one, so `fooAsync` would have been overridden. In order to avoid this - either rename `fooAsync` before promisifying the API, or call [Promise.promisify](.) manually on select properties.
You may also use the custom suffix option to choose another suffix that doesn't result in conflicts.
If you find this issue in a common library please [open an issue](https://github.com/petkaantonov/bluebird/issues/new).
## Error: Catch filter must inherit from Error or be a simple predicate function
Bluebird supports typed and predicate [.catch()](.) calls]. However in order to use the typed/predicate catch syntax for error handling you must do one of two things.
Pass it a constructor that inherits from `Error`:
}).catch(ReferenceError, function(e) { // this is fine
}).catch(Array, function(e) { // arrays don't capture stack traces
This is to enable better stack trace support and to have more consistent and logical code.
Alternatively, if you provide it a predicate be sure it's a simple function:
}).catch(function(e){ return false; }, function(e) { // this catches nothing
}).catch(function(e){ return e.someProp = 5; }, function(e) { // this is fine
Please see the API docs of [.catch()](.) on how to use predicate catches.
## Error: No async scheduler available
Async scheduler is a function that takes a callback function and calls the callback function as soon as possible, but asynchronously. For example `setTimeout`.
By default bluebird only tries a few common async schedulers, such as `setTimeout`, `process.nextTick` and `MutationObserver`. However if your JavaScript runtime environment doesn't expose any of these, you will see this error.
You may use [Promise.setScheduler](.) to pass a custom scheduler that your environment supports. For example in DukTape:
```js
Promise.setScheduler(function(fn){ // fn is what to execute
var timer = uv.new_timer.call({});
uv.timer_start(timer, 0, 0, fn); // add the function as a callback to the timer
});
```
================================================
FILE: docs/docs/features.md
================================================
---
id: features
title: Features
---
[features](unfinished-article)
- [Synchronous inspection](#synchronous-inspection)
- [Concurrency coordination](#concurrency-coordination)
- [Promisification on steroids](#promisification-on-steroids)
- [Debuggability and error handling](#debuggability-and-error-handling)
- [Resource management](#resource-management)
- [Cancellation and timeouts](#cancellation-and-timeouts)
- [Scoped prototypes](#scoped-prototypes)
- [Promise monitoring](#promise-monitoring)
- [Async/Await](#async-await)
##Synchronous inspection
Synchronous inspection allows you to retrieve the fulfillment value of an already fulfilled promise or the rejection reason of an already rejected promise synchronously.
Often it is known in certain code paths that a promise is guaranteed to be fulfilled at that point - it would then be extremely inconvenient to use [`.then`](.) to get at the promise's value as the callback is always called asynchronously.
See the API on [synchronous inspection](.) for more information.
##Concurrency coordination
Through the use of [.each](.) and [.map](.) doing things just at the right concurrency level becomes a breeze.
##Promisification on steroids
Promisification means converting an existing promise-unaware API to a promise-returning API.
The usual way to use promises in node is to [Promise.promisifyAll](.) some API and start exclusively calling promise returning versions of the APIs methods. E.g.
```js
var fs = require("fs");
Promise.promisifyAll(fs);
// Now you can use fs as if it was designed to use bluebird promises from the beginning
fs.readFileAsync("file.js", "utf8").then(...)
```
Note that the above is an exceptional case because `fs` is a singleton instance. Most libraries can be promisified by requiring the library's classes (constructor functions) and calling promisifyAll on the `.prototype`. This only needs to be done once in the entire application's lifetime and after that you may use the library's methods exactly as they are documented, except by appending the `"Async"`-suffix to method calls and using the promise interface instead of the callback interface.
As a notable exception in `fs`, `fs.existsAsync` doesn't work as expected, because Node's `fs.exists` doesn't call back with error as first argument. More at [#418](.). One possible workaround is using `fs.statAsync`.
Some examples of the above practice applied to some popular libraries:
```js
// The most popular redis module
var Promise = require("bluebird");
Promise.promisifyAll(require("redis"));
```
```js
// The most popular mongodb module
var Promise = require("bluebird");
Promise.promisifyAll(require("mongodb"));
```
```js
// The most popular mysql module
var Promise = require("bluebird");
// Note that the library's classes are not properties of the main export
// so we require and promisifyAll them manually
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
```
```js
// Mongoose
var Promise = require("bluebird");
Promise.promisifyAll(require("mongoose"));
```
```js
// Request
var Promise = require("bluebird");
Promise.promisifyAll(require("request"));
// Use request.getAsync(...) not request(..), it will not return a promise
```
```js
// mkdir
var Promise = require("bluebird");
Promise.promisifyAll(require("mkdirp"));
// Use mkdirp.mkdirpAsync not mkdirp(..), it will not return a promise
```
```js
// winston
var Promise = require("bluebird");
Promise.promisifyAll(require("winston"));
```
```js
// rimraf
var Promise = require("bluebird");
// The module isn't promisified but the function returned is
var rimrafAsync = Promise.promisify(require("rimraf"));
```
```js
// xml2js
var Promise = require("bluebird");
Promise.promisifyAll(require("xml2js"));
```
```js
// jsdom
var Promise = require("bluebird");
Promise.promisifyAll(require("jsdom"));
```
```js
// fs-extra
var Promise = require("bluebird");
Promise.promisifyAll(require("fs-extra"));
```
```js
// prompt
var Promise = require("bluebird");
Promise.promisifyAll(require("prompt"));
```
```js
// Nodemailer
var Promise = require("bluebird");
Promise.promisifyAll(require("nodemailer"));
```
```js
// ncp
var Promise = require("bluebird");
Promise.promisifyAll(require("ncp"));
```
```js
// pg
var Promise = require("bluebird");
Promise.promisifyAll(require("pg"));
```
In all of the above cases the library made its classes available in one way or another. If this is not the case, you can still promisify by creating a throwaway instance:
```js
var ParanoidLib = require("...");
var throwAwayInstance = ParanoidLib.createInstance();
Promise.promisifyAll(Object.getPrototypeOf(throwAwayInstance));
// Like before, from this point on, all new instances + even the throwAwayInstance suddenly support promises
```
See also [`Promise.promisifyAll`](.).
##Debuggability and error handling
- [Surfacing unhandled errors](#surfacing-unhandled-errors)
- [Long stack traces](#long-stack-traces)
- [Error pattern matching](#error-pattern-matching)
- [Warnings](#warnings)
###Surfacing unhandled errors
The default approach of bluebird is to immediately log the stack trace when there is an unhandled rejection. This is similar to how uncaught exceptions cause the stack trace to be logged so that you have something to work with when something is not working as expected.
However because it is possible to handle a rejected promise at any time in the indeterminate future, some programming patterns will result in false positives. Because such programming patterns are not necessary and can always be refactored to never cause false positives, we recommend doing that to keep debugging as easy as possible . You may however feel differently so bluebird provides hooks to implement more complex failure policies.
Such policies could include:
- Logging after the promise became GCd (requires a native node.js module)
- Showing a live list of rejected promises
- Using no hooks and using [`.done`](.) to manually to mark end points where rejections will not be handled
- Swallowing all errors (challenge your debugging skills)
- ...
See [global rejection events](http://bluebirdjs.com/docs/api/error-management-configuration.html#global-rejection-events) to learn more about the hooks.
###Long stack traces
Normally stack traces don't go beyond asynchronous boundaries so their utility is greatly reduced in asynchronous code:
```js
setTimeout(function() {
setTimeout(function() {
setTimeout(function() {
a.b.c;
}, 1);
}, 1)
}, 1)
```
```
ReferenceError: a is not defined
at null._onTimeout file.js:4:13
at Timer.listOnTimeout (timers.js:90:15)
```
Of course you could use hacks like monkey patching or domains but these break down when something can't be monkey patched or new apis are introduced.
Since in bluebird [promisification](.) is made trivial, you can get long stack traces all the time:
```js
var Promise = require("bluebird");
Promise.delay(1)
.delay(1)
.delay(1).then(function() {
a.b.c;
});
```
```
Unhandled rejection ReferenceError: a is not defined
at file.js:6:9
at processImmediate [as _immediateCallback] (timers.js:321:17)
From previous event:
at Object. (file.js:5:15)
at Module._compile (module.js:446:26)
at Object.Module._extensions..js (module.js:464:10)
at Module.load (module.js:341:32)
at Function.Module._load (module.js:296:12)
at Function.Module.runMain (module.js:487:10)
at startup (node.js:111:16)
at node.js:799:3
```
And there is more. 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. All these are non-trivial problems that haunt straight-forward long stack trace implementations.
See [installation](install.html) on how to enable long stack traces in your environment.
###Error pattern matching
Perhaps the greatest thing about promises is that it unifies all error handling into one mechanism where errors propagate automatically and have to be explicitly ignored.
###Warnings
Promises can have a steep learning curve and it doesn't help that promise standards go out of their way to make it even harder. Bluebird works around the limitations by providing warnings where the standards disallow throwing errors when incorrect usage is detected. See [Warning Explanations](warning-explanations.html) for the possible warnings that bluebird covers.
See [installation](install.html) on how to enable warnings in your environment.
Note - in order to get full stack traces with warnings in Node 6.x+ you need to enable to `--trace-warnings` flag which will give you a full stack trace of where the warning is coming from.
###Promise monitoring
This feature enables subscription to promise lifecycle events via standard global events mechanisms in browsers and Node.js.
The following lifecycle events are available:
- `"promiseCreated"` - Fired when a promise is created through the constructor.
- `"promiseChained"` - Fired when a promise is created through chaining (e.g. [.then](.)).
- `"promiseFulfilled"` - Fired when a promise is fulfilled.
- `"promiseRejected"` - Fired when a promise is rejected.
- `"promiseResolved"` - Fired when a promise adopts another's state.
- `"promiseCancelled"` - Fired when a promise is cancelled.
This feature has to be explicitly enabled by calling [Promise.config](.) with `monitoring: true`.
The actual subscription API depends on the environment.
1\. In Node.js, use `process.on`:
```js
// Note the event name is in camelCase, as per Node.js convention.
process.on("promiseChained", function(promise, child) {
// promise - The parent promise the child was chained from
// child - The created child promise.
});
```
2\. In modern browsers use `window.addEventListener` (window context) or `self.addEventListener()` (web worker or window context) method:
```js
// Note the event names are in mashedtogetherlowercase, as per DOM convention.
self.addEventListener("promisechained", function(event) {
// event.details.promise - The parent promise the child was chained from
// event.details.child - The created child promise.
});
```
3\. In legacy browsers use `window.oneventname = handlerFunction;`.
```js
// Note the event names are in mashedtogetherlowercase, as per legacy convention.
window.onpromisechained = function(promise, child) {
// event.details.promise - The parent promise the child was chained from
// event.details.child - The created child promise.
};
```
##Resource management
##Cancellation and timeouts
See [`Cancellation`](.) for how to use cancellation.
```js
// Enable cancellation
Promise.config({cancellation: true});
var fs = Promise.promisifyAll(require("fs"));
// In 2000ms or less, load & parse a file 'config.json'
var p = Promise.resolve('./config.json')
.timeout(2000)
.catch(console.error.bind(console, 'Failed to load config!'))
.then(fs.readFileAsync)
.then(JSON.parse);
// Listen for exception event to trigger promise cancellation
process.on('unhandledException', function(event) {
// cancel config loading
p.cancel();
});
```
##Scoped prototypes
Building a library that depends on bluebird? You should know about the "scoped prototype" feature.
If your library needs to do something obtrusive like adding or modifying methods on the `Promise` prototype, uses long stack traces or uses a custom unhandled rejection handler then... that's totally ok as long as you don't use `require("bluebird")`. Instead you should create a file
that creates an isolated copy. For example, creating a file called `bluebird-extended.js` that contains:
```js
//NOTE the function call right after
module.exports = require("bluebird/js/main/promise")();
```
Your library can then use `var Promise = require("bluebird-extended");` and do whatever it wants with it. Then if the application or other library uses their own bluebird promises they will all play well together because of Promises/A+ thenable assimilation magic.
##Async/Await
================================================
FILE: docs/docs/getting-started.md
================================================
---
id: getting-started
title: Getting Started
redirect_from: "/index.html"
redirect_from: "/docs/index.html"
---
[getting-started](unfinished-article)
## Node.js
npm install bluebird
Then:
```js
var Promise = require("bluebird");
```
Alternatively in ES6
```js
import * as Promise from "bluebird";
```
If that ES6 import [doesn't work](https://github.com/petkaantonov/bluebird/pull/1594)
```js
import {Promise} from "bluebird";
```
## Browsers
(See also [Installation](install.html).)
There are many ways to use bluebird in browsers:
- Direct downloads
- Full build [bluebird.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.js)
- Full build minified [bluebird.min.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.min.js)
- Core build [bluebird.core.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.core.js)
- Core build minified [bluebird.core.min.js](https://cdn.jsdelivr.net/bluebird/latest/bluebird.core.min.js)
- You may use browserify on the main export
- You may use the [bower](http://bower.io) package.
When using script tags the global variables `Promise` and `P` (alias for `Promise`) become available. Bluebird runs on a wide variety of browsers including older versions. We'd like to thank BrowserStack for giving us a free account which helps us test that.
================================================
FILE: docs/docs/install.md
================================================
---
id: install
title: Installation
---
- [Browser installation](#browser-installation)
- [Node installation](#node-installation)
- [Supported platforms](#supported-platforms)
##Browser installation
Download bluebird {{ site.version }} (development)
Unminified source file meant to be used in development. Warnings and long stack traces are enabled which are taxing on performance.
```html
```
Download bluebird {{ site.version }} (production)
Minified source file meant to be used in production. Warnings and long straces are disabled. The gzipped size is 17.76KB.
```html
```
Unless an AMD loader is installed, the script tag installation exposes the library in the `Promise` and `P` namespaces. If you want to restore the `Promise` namespace, use `var Bluebird = Promise.noConflict()`.
###Bower
```
$ bower install --save bluebird
```
###Browserify and Webpack
```
$ npm install bluebird
```
Using webpack for development/debugging:
```js
var Promise = require("bluebird");
// Configure webpack and browserify for development/debugging
Promise.config({
longStackTraces: true,
warnings: true // note, run node with --trace-warnings to see full stack traces for warnings
})
```
Using webpack for production/performance:
```js
var Promise = require("bluebird");
// Configure webpack and browserify for production/performance
Promise.config({
longStackTraces: false,
warnings: false
})
```
##Node installation
```
$ npm install bluebird
```
```js
var Promise = require("bluebird");
```
To enable long stack traces and warnings in node development:
```
$ NODE_ENV=development node server.js
```
To enable long stack traces and warnings in node production:
```
$ BLUEBIRD_DEBUG=1 node server.js
```
See [Environment Variables](.).
##Supported platforms
Bluebird officially supports and is tested on node.js, iojs and browsers starting from IE7. Unofficial platforms are supported with best effort only.
IE7 and IE8 do not support using keywords as property names, so if supporting these browsers is required you need to use the compatibility aliases:
- [`Promise.try()`](.) -> `Promise.attempt()`
- [`.catch()`](.) -> `.caught()`
- [`.finally()`](.) -> `.lastly()`
- [`.return()`](.) -> `.thenReturn()`
- [`.throw()`](.) -> `.thenThrow()`
Long stack traces are only supported in Chrome, recent Firefoxes and Internet Explorer 10+
[](https://saucelabs.com/u/petka_antonov)
================================================
FILE: docs/docs/new-in-bluebird-3.md
================================================
---
id: new-in-bluebird-3
title: New in bluebird 3.0
---
##Cancellation overhaul
Cancellation has been redesigned for bluebird 3.0. Any code that relies on 2.x cancellation semantics won't work in 3.0 or later. See [Cancellation](.) for more information.
##Promisification API changes
Both promisification \([Promise.promisify](.) and [Promise.promisifyAll](.)\) methods and [Promise.fromCallback](.) now by default ignore multiple arguments passed to the callback adapter and instead only the first argument is used to resolve the promise. The behavior in 2.x is to construct an array of the arguments and resolve the promise with it when more than one argument is passed to the callback adapter. The problems with this approach and reasons for the change are discussed in [#307](.).
[Promise.promisify](.)'s second argument is now an options object, so any code using the second argument needs to change:
```js
// 2.x
Promise.promisify(fn, ctx);
// 3.0
Promise.promisify(fn, {context: ctx});
```
Both promisification \([Promise.promisify](.) and [Promise.promisifyAll](.)\) methods and [Promise.fromCallback](.) all take a new boolean option `multiArgs` which defaults to `false`. Enabling this option will make the adapter callback *always* construct an array of the passed arguments regardless of amount of arguments. This can be used to reliably get access to all arguments rather than just the first one.
##Collection method changes
All collection methods now support objects that implement [ES6's *iterable*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) protocol along with regular arrays.
[Promise.props](.) and [.props](.) now support [ES6 `Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) objects along with normal objects. Actual `Map` objects are only considered for their entries in the map instead of both entries and properties.
##Warnings
Warnings have been added to report usages which are very likely to be programmer errors. See [Promise.config](.) for how to enable warnings. See [Warning Explanations](warning-explanations.html) for list of the warnings and their explanations.
##Feature additions
- [.catch\(\)](.) now supports an object predicate as a filter: `.catch({code: 'ENOENT'}, e => ...)`.
- Added [.suppressUnhandledRejections\(\)](.).
- Added [.catchThrow\(\)](.).
- Added [.catchReturn\(\)](.).
- Added [Promise.mapSeries\(\)](.) and [.mapSeries\(\)](.)
##Deprecations
- `Promise.settle` has been deprecated. Use [.reflect](.) instead.
- `Promise.spawn` has been deprecated. Use [Promise.coroutine](.) instead.
- [Promise.try](.)'s `ctx` and `arg` arguments have been deprecated.
- `.nodeify` is now better known as [.asCallback](.)
- `.fromNode` is now better known as [Promise.fromCallback](.)
##Summary of breaking changes
- Promisifier APIs.
- Cancellation redesign.
- Promise progression has been completely removed.
- [.spread](.)'s second argument has been removed.
- [.done](.) causes an irrecoverable fatal error in Node.js environments now. See [#471](.) for rationale.
- Errors created with [Promise.reject](.) or `reject` callback of [new Promise](.) are no longer marked as [OperationalError](.)s.
##3.0.1 update
Note that the 3.0.1 update is strictly speaking backward-incompatible with 3.0.0. Version 3.0.0 changed the previous behavior of the `.each` method and made it work the same as the new `.mapSeries` - 3.0.1 unrolls this change by reverting to the `.tap`-like behavior found in 2.x However, this would only affect users who updated to 3.0.0 during the short time that it wasn't deprecated and started relying on the new `.each` behavior. This seems unlikely, and therefore the major version was not changed.
================================================
FILE: docs/docs/support.md
================================================
---
id: support
title: Support
---
Depending on the nature of your problem there are a few possible ways of getting help with your problem.
###Stack Overflow
Stack Overflow has an active community answering questions on both the [bluebird](http://stackoverflow.com/questions/tagged/bluebird) and [promise](http://stackoverflow.com/questions/tagged/promise) tags. If you are unfamiliar with Stack Overflow, do review [the asking guidelines](http://stackoverflow.com/help/asking) before asking a new question there.
###Google Groups mailing list
The [bluebird-js@googlegroups.com](https://groups.google.com/forum/#!forum/bluebird-js) mailing list is the best place to ask any question that cannot be easily fit in the stack overflow question format.
###IRC
You can usually get fast answers on the freenode.net channels [#bluebird](irc://chat.freenode.net/bluebird) and [#promises](irc://chat.freenode.net/promises).
###Gitter
If you are not comfortable using IRC you can also join the [bluebird gitter chat](https://gitter.im/petkaantonov/bluebird)
###Github issue tracker
If you feel that your problem is caused by a bug or a missing feature that should be added, you should use the [Github issue tracker](https://github.com/petkaantonov/bluebird/issues/) to report it. However in any other case the issue tracker is not the appropriate channel.
================================================
FILE: docs/docs/warning-explanations.md
================================================
---
id: warning-explanations
title: Warning Explanations
---
[warning-explanations](unfinished-article)
- [Warning: .then() only accepts functions](#warning-then-only-accepts-functions)
- [Warning: a promise was rejected with a non-error](#warning-a-promise-was-rejected-with-a-non-error)
- [Warning: a promise was created in a handler but was not returned from it](#warning-a-promise-was-created-in-a-handler-but-was-not-returned-from-it)
Note - in order to get full stack traces with warnings in Node 6.x+ you need to enable to `--trace-warnings` flag which will give you a full stack trace of where the warning is coming from.
## Warning: .then() only accepts functions
If you see this warning your code is probably not doing what you expect it to, the most common reason is passing the *result* of calling a function to [.then()](.) instead of the function *itself*:
```js
function processImage(image) {
// Code that processes image
}
getImage().then(processImage());
```
The above calls the function `processImage()` *immediately* and passes the result to [.then()](.) (which is most likely `undefined` - the default return value when a function doesn't return anything).
To fix it, simply pass the function reference to [.then()](.) as is:
```js
getImage().then(processImage)
```
*If you are wondering why this is a warning and not a simple TypeError it is because the due to historic reasons Promises/A+ specification requires that incorrect usage is silently ignored.*
## Warning: a promise was rejected with a non-error
Due to a historic mistake in JavaScript, the `throw` statement is allowed to be used with any value, not just errors, and Promises/A+ choosing to inherit this mistake, it is possible to reject a promise with a value that is not an error.
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. This is because errors are usually handled many levels above where they actually originate - the error object must have sufficient metadata about it so that its ultimate handler (possibly many levels above) will have all the information needed for creating a useful high level error report.
Since all objects support having properties you might still wonder why exactly does it have to be an error object and not just any object. In addition to supporting properties, an equally important feature necessary for values that are automatically propagated is the stack trace property (`.stack`). A stack trace allows you easily find where an error originated from as it gives the code's call stack - along with line numbers for reference in code files.
You should heed this warning because rejecting a promise with a non-error makes debugging extremely hard and costly. Additionally, if you reject with simple primitives such as `undefined` (commonly caused by simply calling `reject()`) you cannot handle errors at all because it's impossible to tell from `undefined` what exactly went wrong. All you can tell the user is that "something went wrong" and lose them forever.
## Warning: a promise was created in a handler but was not returned from it
This usually means that you simply forgot a `return` statement somewhere, which will cause a runaway promise that is not connected to any promise chain.
For example:
```js
getUser().then(function(user) {
getUserData(user);
}).then(function(userData) {
// userData is undefined
});
```
Because the result of `getUserData()` is not returned from the first then handler, it becomes a runaway promise that is not awaited for by the second then. The second [.then()](.) simply gets immediately called with `undefined` (because `undefined` is the default return value when you don't return anything).
To fix it, you need to `return` the promise:
```js
getUser().then(function(user) {
return getUserData(user);
}).then(function(userData) {
// userData is the user's data
});
```
If you know what you're doing and don't want to silence all warnings, you can create runaway promises without causing this warning by returning e.g. `null`:
```js
getUser().then(function(user) {
// Perform this in the "background" and don't care about its result at all
saveAnalytics(user);
// return a non-undefined value to signal that we didn't forget to return
return null;
});
```
================================================
FILE: docs/docs/what-about-generators.md
================================================
---
id: what-about-generators
title: What About Generators?
---
There is an [excellent article](https://www.promisejs.org/generators/) on promisejs.org detailing how to combine promises with generators to achieve much cleaner code. Instead of the `async` function the article proposes, you can use [Promise.coroutine](.).
[what-about-generators](unfinished-article)
================================================
FILE: docs/docs/why-bluebird.md
================================================
---
id: why-bluebird
title: Why bluebird?
---
There are many third party promise libraries available for JavaScript and even the standard library contains a promise implementation in newer versions of browsers and node/io.js. This page will explore why one might use bluebird promises over other third party or the standard library implementations. For reasons to use promises in general, see the [Why Promises?](why-promises.html) article.
###Bluebird design principles
Bluebird is built with the following design principles in mind:
- **Pragmatic and not theoretical** - Bluebird will always pick the pragmatic route vs the theoretically elegant one when there is a conflict. The library's API was created based on real-life use cases and after a lot of consideration.
- **Fully featured without bloat** - Bluebird provides all the tools and utilities needed to realize a highly expressive and fluent DSL for asynchronous JavaScript without suffering from bloat by avoiding incorporating features that are solely motivated by theoretical arguments, have extremely narrow applicability, or have limited synergy and composability with existing features.
- **Easy to debug** - A major consequence of choosing pragmatism over theoretical elegance, a property that is unique to bluebird among promise libraries taken to this extent.
- Bluebird ships with the best cross-platform long stack traces out there and a warning system. This helps you recognize common and devastating promise usage mistakes early before they lead to hard to debug code later.
- Unhandled errors are not silently swallowed by default but reported along with helpful stack traces where applicable. All of this is of course configurable.
- **Zero overhead abstraction** - In server-side applications the performance of a promise implementation matters. Bluebird's server-side performance is measured with highly relevant and realistic end-to-end macro [benchmarks](benchmarks.html), and consistently comes out on top. We understand that if bluebird is as close to a zero cost abstraction as possible, developers won't be tempted to short-circuit and absorb complexity themselves.
- **Runs everywhere** - Bluebird runs on pretty much every platform. This makes bluebird ideal for projects who care about providing consistent cross-platform and cross-version experience. It runs on old IE, it has even been known to run on Netscape 7.
- **Spec compatible** - Bluebird can work as a drop-in replacement for native promises for an instant performance boost. It passes the Promises/A+ test suite and is fully spec compliant.
================================================
FILE: docs/docs/why-performance.md
================================================
---
id: why-performance
title: Why Performance?
---
[why-performance](unfinished-article)
================================================
FILE: docs/docs/why-promises.md
================================================
---
id: why-promises
title: Why Promises?
---
Promises are a concurrency primitive with a proven track record and language integration in most modern programming languages. They have been extensively studied since the 80s and will make your life much easier.
You should use promises to turn this:
```js
fs.readFile("file.json", function (err, val) {
if (err) {
console.error("unable to read file");
}
else {
try {
val = JSON.parse(val);
console.log(val.success);
}
catch (e) {
console.error("invalid json in file");
}
}
});
```
Into this:
```js
fs.readFileAsync("file.json").then(JSON.parse).then(function (val) {
console.log(val.success);
})
.catch(SyntaxError, function (e) {
console.error("invalid json in file");
})
.catch(function (e) {
console.error("unable to read file");
});
```
*If you're thinking, "There's no `readFileAsync` method on `fs` that returns a promise!" see [promisification](api/promisification.html)*
You might notice that the promise approach looks very similar to using synchronous I/O:
```js
try {
var val = JSON.parse(fs.readFileSync("file.json"));
console.log(val.success);
}
// Gecko-only syntax; used for illustrative purposes
catch (e if e instanceof SyntaxError) {
console.error("invalid json in file");
}
catch (e) {
console.error("unable to read file");
}
```
This is the point—to have something that works like `return` and `throw` in synchronous code.
You can also use promises to improve code that was written with callbacks:
```js
//Copyright Plato http://stackoverflow.com/a/19385911/995876
//CC BY-SA 2.5
mapSeries(URLs, function (URL, done) {
var options = {};
needle.get(URL, options, function (error, response, body) {
if (error) {
return done(error);
}
try {
var ret = JSON.parse(body);
return done(null, ret);
}
catch (e) {
done(e);
}
});
}, function (err, results) {
if (err) {
console.log(err);
} else {
console.log('All Needle requests successful');
// results is a 1 to 1 mapping in order of URLs > needle.body
processAndSaveAllInDB(results, function (err) {
if (err) {
return done(err);
}
console.log('All Needle requests saved');
done(null);
});
}
});
```
This is far more readable when done with promises:
```js
Promise.promisifyAll(needle);
var options = {};
var current = Promise.resolve();
Promise.map(URLs, function (URL) {
current = current.then(function () {
return needle.getAsync(URL, options);
});
return current;
}).map(function (responseAndBody) {
return JSON.parse(responseAndBody[1]);
}).then(function (results) {
return processAndSaveAllInDB(results);
}).then(function () {
console.log('All Needle requests saved');
}).catch(function (e) {
console.log(e);
});
```
Also, promises don't just give you correspondences for synchronous features; they can also be used as limited event emitters or callback aggregators.
More reading:
- [Promise nuggets](https://promise-nuggets.github.io/)
- [Why I am switching to promises](http://spion.github.io/posts/why-i-am-switching-to-promises.html)
- [What is the the point of promises](http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/#toc_1)
- [Aren't Promises Just Callbacks?](http://stackoverflow.com/questions/22539815/arent-promises-just-callbacks)
================================================
FILE: docs/docs/working-with-callbacks.md
================================================
---
id: working-with-callbacks
title: Working with Callbacks
---
This page explains how to interface your code with existing callback APIs and libraries you're using. We'll see that making bluebird work with callback APIs is not only easy - it's also fast.
We'll cover several subjects. If you want to get the tl;dr what you need is likely the [Working with callback APIs using the Node convention](#working-with-callback-apis-using-the-node-convention) section.
First to make sure we're on the same page:
Promises have state, they start as pending and can settle to:
- __fulfilled__ meaning that the computation completed successfully.
- __rejected__ meaning that the computation failed.
Promise returning functions _should never throw_, they should always successfully return a promise which is rejected in the case of an error. Throwing from a promise returning function will force you to use both a `} catch { ` _and_ a `.catch`. People using promisified APIs do not expect promises to throw. If you're not sure how async APIs work in JS - please [see this answer](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call/16825593#16825593) first.
* [Automatic vs. Manual conversion](#automatic-vs.-manual-conversion)
* [Working with callback APIs using the Node convention](#working-with-callback-apis-using-the-node-convention)
* [Working with one time events.](#working-with-one-time-events)
* [Working with delays](#working-with-delays/setTimeout)
* [Working with browser APIs](#working-with-browser-apis)
* [Working with databases](#working-with-databases)
* [More Common Examples](#more-common-examples)
* [Working with any other APIs](#working-with-any-other-apis)
There is also [this more general StackOverflow question](http://stackoverflow.com/questions/22519784/how-do-i-convert-an-existing-callback-api-to-promises) about conversion of callback APIs to promises. If you find anything missing in this guide however, please do open an issue or pull request.
###Automatic vs. Manual conversion
There are two primary methods of converting callback based APIs into promise based ones. You can either manually map the API calls to promise returning functions or you can let the bluebird do it for you. We **strongly** recommend the latter.
Promises provide a lot of really cool and powerful guarantees like throw safety which are hard to provide when manually converting APIs to use promises. Thus, whenever it is possible to use the `Promise.promisify` and `Promise.promisifyAll` methods - we recommend you use them. Not only are they the safest form of conversion - they also use techniques of dynamic recompilation to introduce very little overhead.
###Working with callback APIs using the Node convention
In Node/io.js most APIs follow a convention of ['error-first, single-parameter'](https://gist.github.com/CrabDude/10907185) as such:
```js
function getStuff(data, callback) {
...
}
getStuff("dataParam", function(err, data) {
if (!err) {
}
});
```
This APIs are what most core modules in Node/io use and bluebird comes with a fast and efficient way to convert them to promise based APIs through the `Promise.promisify` and `Promise.promisifyAll` function calls.
- [Promise.promisify](.) - converts a _single_ callback taking function into a promise returning function. It does not alter the original function and returns the modified version.
- [Promise.promisifyAll](.) - takes an _object_ full of functions and _converts each function_ into the new one with the `Async` suffix (by default). It does not change the original functions but instead adds new ones.
> **Note** - please check the linked docs for more parameters and usage examples.
Here's an example of `fs.readFile` with or without promises:
```js
// callbacks
var fs = require("fs");
fs.readFile("name", "utf8", function(err, data) {
});
```
Promises:
```js
var fs = Promise.promisifyAll(require("fs"));
fs.readFileAsync("name", "utf8").then(function(data) {
});
```
Note the new method is suffixed with `Async`, as in `fs.readFileAsync`. It did not replace the `fs.readFile` function. Single functions can also be promisified for example:
```js
var request = Promise.promisify(require("request"));
request("foo.bar").then(function(result) {
});
```
> **Note** `Promise.promisify` and `Promise.promisifyAll` use 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.
###Working with one time events
Sometimes, we want to find out when a single one time event has finished. For example - a stream is done. For this we can use [new Promise](.). Note that this option should be considered only if [automatic conversion](#working-with-callback-apis-using-the-node-convention) isn't possible.
Note that promises model a _single value through time_, they only resolve _once_ - so while they're a good fit for a single event, they are not recommended for multiple event APIs.
For example, let's say you have a window `onload` event you want to bind to. We can use the promise construction and resolve when the window has loaded as such:
```js
// onload example, the promise constructor takes a
// 'resolver' function that tells the promise when
// to resolve and fire off its `then` handlers.
var loaded = new Promise(function(resolve, reject) {
window.addEventListener("load", resolve);
});
loaded.then(function() {
// window is loaded here
});
```
Here is another example with an API that lets us know when a connection is ready. The attempt here is imperfect and we'll describe why soon:
```js
function connect() {
var connection = myConnector.getConnection(); // Synchronous.
return new Promise(function(resolve, reject) {
connection.on("ready", function() {
// When a connection has been established
// mark the promise as fulfilled.
resolve(connection);
});
connection.on("error", function(e) {
// If it failed connecting, mark it
// as rejected.
reject(e); // e is preferably an `Error`.
});
});
}
```
The problem with the above is that `getConnection` itself might throw for some reason and if it does we'll get a synchronous rejection. An asynchronous operation should always be asynchronous to prevent double guarding and race conditions so it's best to always put the sync parts inside the promise constructor as such:
```js
function connect() {
return new Promise(function(resolve, reject) {
// If getConnection throws here instead of getting
// an exception we're getting a rejection thus
// producing a much more consistent API.
var connection = myConnector.getConnection();
connection.on("ready", function() {
// When a connection has been established
// mark the promise as fulfilled.
resolve(connection);
});
connection.on("error", function(e) {
// If it failed connecting, mark it
// as rejected.
reject(e); // e is preferably an `Error`
});
});
}
```
###Working with delays/setTimeout
There is no need to convert timeouts/delays to a bluebird API, bluebird already ships with the [Promise.delay](.) function for this use case. Please consult the [timers](.) section of the docs on usage and examples.
###Working with browser APIs
Often browser APIs are nonstandard and automatic promisification will fail for them. If you're running into an API that you can't promisify with [promisify](.) and [promisifyAll](.) - please consult the [working with other APIs section](#working-with-any-other-apis)
###Working with databases
For resource management in general and databases in particular, bluebird includes the powerful [Promise.using](.) and disposers system. This is similar to `with` in Python, `using` in C#, try/resource in Java or RAII in C++ in that it lets you handle resource management in an automatic way.
Several examples of databases follow.
> **Note** for more examples please see the [Promise.using](.) section.
####Mongoose/MongoDB
Mongoose works with persistent connections and the driver takes care of reconnections/disposals. For this reason using `using` with it isn't required - instead connect on server startup and use promisification to expose promises.
Note that Mongoose already ships with promise support but the promises it offers are significantly slower and don't report unhandled rejections so it is recommended to use automatic promisification with it anyway:
```js
var Mongoose = Promise.promisifyAll(require("mongoose"));
```
####Sequelize
Sequelize already uses Bluebird promises internally and has promise returning APIs. Use those.
####RethinkDB
Rethink already uses Bluebird promises internally and has promise returning APIs. Use those.
####Bookshelf
Bookshelf already uses Bluebird promises internally and has promise returning APIs. Use those.
####PostgreSQL
Here is how to create a disposer for the PostgreSQL driver:
```js
var pg = require("pg");
// Uncomment if pg has not been properly promisified yet.
//var Promise = require("bluebird");
//Promise.promisifyAll(pg, {
// filter: function(methodName) {
// return methodName === "connect"
// },
// multiArgs: true
//});
// Promisify rest of pg normally.
//Promise.promisifyAll(pg);
function getSqlConnection(connectionString) {
var close;
return pg.connectAsync(connectionString).spread(function(client, done) {
close = done;
return client;
}).disposer(function() {
if (close) close();
});
}
module.exports = getSqlConnection;
```
Which would allow you to use:
```js
var using = Promise.using;
using(getSqlConnection(), function(conn) {
// use connection here and _return the promise_
}).then(function(result) {
// connection already disposed here
});
```
It's also possible to use a disposer pattern (but not actual disposers) for transaction management:
```js
function withTransaction(fn) {
return Promise.using(pool.acquireConnection(), function(connection) {
var tx = connection.beginTransaction()
return Promise
.try(fn, tx)
.then(function(res) { return connection.commit().thenReturn(res) },
function(err) {
return connection.rollback()
.catch(function(e) {/* maybe add the rollback error to err */})
.thenThrow(err);
});
});
}
exports.withTransaction = withTransaction;
```
Which would let you do:
```js
withTransaction(tx => {
return tx.queryAsync(...).then(function() {
return tx.queryAsync(...)
}).then(function() {
return tx.queryAsync(...)
});
});
```
####MySQL
Here is how to create a disposer for the MySQL driver:
```js
var mysql = require("mysql");
// Uncomment if mysql has not been properly promisified yet
// var Promise = require("bluebird");
// Promise.promisifyAll(mysql);
// Promise.promisifyAll(require("mysql/lib/Connection").prototype);
// Promise.promisifyAll(require("mysql/lib/Pool").prototype);
var pool = mysql.createPool({
connectionLimit: 10,
host: 'example.org',
user: 'bob',
password: 'secret'
});
function getSqlConnection() {
return pool.getConnectionAsync().disposer(function(connection) {
connection.release();
});
}
module.exports = getSqlConnection;
```
The usage pattern is similar to the PostgreSQL example above. You can also use a disposer pattern (but not an actual .disposer). See the PostgreSQL example above for instructions.
###More common examples
Some examples of the above practice applied to some popular libraries:
```js
// The most popular redis module
var Promise = require("bluebird");
Promise.promisifyAll(require("redis"));
```
```js
// The most popular mongodb module
var Promise = require("bluebird");
Promise.promisifyAll(require("mongodb"));
```
```js
// The most popular mysql module
var Promise = require("bluebird");
// Note that the library's classes are not properties of the main export
// so we require and promisifyAll them manually
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);
```
```js
// Mongoose
var Promise = require("bluebird");
Promise.promisifyAll(require("mongoose"));
```
```js
// Request
var Promise = require("bluebird");
Promise.promisifyAll(require("request"));
// Use request.getAsync(...) not request(..), it will not return a promise
```
```js
// mkdir
var Promise = require("bluebird");
Promise.promisifyAll(require("mkdirp"));
// Use mkdirp.mkdirpAsync not mkdirp(..), it will not return a promise
```
```js
// winston
var Promise = require("bluebird");
Promise.promisifyAll(require("winston"));
```
```js
// rimraf
var Promise = require("bluebird");
// The module isn't promisified but the function returned is
var rimrafAsync = Promise.promisify(require("rimraf"));
```
```js
// xml2js
var Promise = require("bluebird");
Promise.promisifyAll(require("xml2js"));
```
```js
// jsdom
var Promise = require("bluebird");
Promise.promisifyAll(require("jsdom"));
```
```js
// fs-extra
var Promise = require("bluebird");
Promise.promisifyAll(require("fs-extra"));
```
```js
// prompt
var Promise = require("bluebird");
Promise.promisifyAll(require("prompt"));
```
```js
// Nodemailer
var Promise = require("bluebird");
Promise.promisifyAll(require("nodemailer"));
```
```js
// ncp
var Promise = require("bluebird");
Promise.promisifyAll(require("ncp"));
```
```js
// pg
var Promise = require("bluebird");
Promise.promisifyAll(require("pg"));
```
In all of the above cases the library made its classes available in one way or another. If this is not the case, you can still promisify by creating a throwaway instance:
```js
var ParanoidLib = require("...");
var throwAwayInstance = ParanoidLib.createInstance();
Promise.promisifyAll(Object.getPrototypeOf(throwAwayInstance));
// Like before, from this point on, all new instances + even the throwAwayInstance suddenly support promises
```
###Working with any other APIs
Sometimes you have to work with APIs that are inconsistent and do not follow a common convention.
> **Note** Promise returning function should never throw
For example, something like:
```js
function getUserData(userId, onLoad, onFail) { ...
```
We can use the promise constructor to convert it to a promise returning function:
```js
function getUserDataAsync(userId) {
return new Promise(function(resolve, reject) {
// Put all your code here, this section is throw-safe.
getUserData(userId, resolve, reject);
});
}
```
================================================
FILE: docs/helpers.rb
================================================
require "sanitize"
class Helpers
def self.clean(input)
return Sanitize.fragment(input)
.downcase
.gsub(/\s+/, "-")
.gsub(/^([A-Za-z0-9\-_.:]+).*?$/, "\\1")
.gsub(/^\./, "")
.gsub(/\.$/, "")
.gsub(/[^A-Za-z0-9\-_.]/, "")
.sub(/^-+/, "")
.sub(/-+$/, "")
end
end
================================================
FILE: docs/img/README.txt
================================================
SVG available upon request.
================================================
FILE: docs/index.html
================================================
Redirecting...
Redirecting...
Click here if you are not redirected.
================================================
FILE: issue_template.md
================================================
(This issue tracker is only for bug reports or feature requests, if this is neither, please choose appropriate channel from http://bluebirdjs.com/docs/support.html)
Please answer the questions the best you can:
1) What version of bluebird is the issue happening on?
2) What platform and version? (For example Node.js 0.12 or Google Chrome 32)
3) Did this issue happen with earlier version of bluebird?
(Write description of your issue here, stack traces from errors and code that reproduces the issue are helpful)
================================================
FILE: package.json
================================================
{
"name": "bluebird",
"description": "Full featured Promises/A+ implementation with exceptionally good performance",
"version": "3.7.2",
"keywords": [
"promise",
"performance",
"promises",
"promises-a",
"promises-aplus",
"async",
"await",
"deferred",
"deferreds",
"future",
"flow control",
"dsl",
"fluent interface"
],
"scripts": {
"lint": "node scripts/jshint.js",
"test": "node --expose-gc tools/test.js",
"istanbul": "istanbul",
"prepublish": "npm run generate-browser-core && npm run generate-browser-full",
"generate-browser-full": "node tools/build.js --no-clean --no-debug --release --browser --minify",
"generate-browser-core": "node tools/build.js --features=core --no-debug --release --zalgo --browser --minify && mv js/browser/bluebird.js js/browser/bluebird.core.js && mv js/browser/bluebird.min.js js/browser/bluebird.core.min.js"
},
"homepage": "https://github.com/petkaantonov/bluebird",
"repository": {
"type": "git",
"url": "git://github.com/petkaantonov/bluebird.git"
},
"bugs": {
"url": "http://github.com/petkaantonov/bluebird/issues"
},
"license": "MIT",
"author": {
"name": "Petka Antonov",
"email": "petka_antonov@hotmail.com",
"url": "http://github.com/petkaantonov/"
},
"devDependencies": {
"acorn": "^6.0.2",
"acorn-walk": "^6.1.0",
"baconjs": "^0.7.43",
"bluebird": "^2.9.2",
"body-parser": "^1.10.2",
"browserify": "^8.1.1",
"cli-table": "~0.3.1",
"co": "^4.2.0",
"cross-spawn": "^0.2.3",
"glob": "^4.3.2",
"grunt-saucelabs": "~8.6.3",
"highland": "^2.3.0",
"istanbul": "^0.3.5",
"jshint": "^2.6.0",
"jshint-stylish": "~0.2.0",
"kefir": "^2.4.1",
"mkdirp": "~0.5.0",
"mocha": "~10.2",
"open": "~0.0.5",
"optimist": "~0.6.1",
"rimraf": "~2.2.6",
"rx": "^2.3.25",
"serve-static": "^1.7.1",
"sinon": "~1.7.3",
"uglify-js": "~2.4.16"
},
"readmeFilename": "README.md",
"main": "./js/release/bluebird.js",
"webpack": "./js/release/bluebird.js",
"browser": "./js/browser/bluebird.js",
"files": [
"js/browser",
"js/release",
"LICENSE"
]
}
================================================
FILE: src/any.js
================================================
"use strict";
module.exports = function(Promise) {
var SomePromiseArray = Promise._SomePromiseArray;
var ASSERT = require("./assert");
function any(promises) {
var ret = new SomePromiseArray(promises);
var promise = ret.promise();
ASSERT(promise.isPending());
ASSERT(ret instanceof SomePromiseArray);
ret.setHowMany(1);
ret.setUnwrap();
ret.init();
return promise;
}
Promise.any = function (promises) {
return any(promises);
};
Promise.prototype.any = function () {
return any(this);
};
};
================================================
FILE: src/assert.js
================================================
"use strict";
module.exports = (function(){
var AssertionError = (function() {
function AssertionError(a) {
this.constructor$(a);
this.message = a;
this.name = "AssertionError";
}
AssertionError.prototype = new Error();
AssertionError.prototype.constructor = AssertionError;
AssertionError.prototype.constructor$ = Error;
return AssertionError;
})();
function getParams(args) {
var params = [];
for (var i = 0; i < args.length; ++i) params.push("arg" + i);
return params;
}
function nativeAssert(callName, args, expect) {
try {
var params = getParams(args);
var constructorArgs = params;
constructorArgs.push("return " +
callName + "("+ params.join(",") + ");");
var fn = Function.apply(null, constructorArgs);
return fn.apply(null, args);
} catch (e) {
if (!(e instanceof SyntaxError)) {
throw e;
} else {
return expect;
}
}
}
return function assert(boolExpr, message) {
if (boolExpr === true) return;
if (typeof boolExpr === "string" &&
boolExpr.charAt(0) === "%") {
var nativeCallName = boolExpr;
INLINE_SLICE(args, arguments, 2);
if (nativeAssert(nativeCallName, args, message) === message) return;
message = (nativeCallName + " !== " + message);
}
var ret = new AssertionError(message);
if (Error.captureStackTrace) {
Error.captureStackTrace(ret, assert);
}
throw ret;
};
})();
================================================
FILE: src/async.js
================================================
"use strict";
var firstLineError;
try {throw new Error(); } catch (e) {firstLineError = e;}
var ASSERT = require("./assert");
var schedule = require("./schedule");
var Queue = require("./queue");
function Async() {
this._customScheduler = false;
this._isTickUsed = false;
this._lateQueue = new Queue(LATE_QUEUE_CAPACITY);
this._normalQueue = new Queue(NORMAL_QUEUE_CAPACITY);
this._haveDrainedQueues = false;
var self = this;
this.drainQueues = function () {
self._drainQueues();
};
this._schedule = schedule;
}
Async.prototype.setScheduler = function(fn) {
var prev = this._schedule;
this._schedule = fn;
this._customScheduler = true;
return prev;
};
Async.prototype.hasCustomScheduler = function() {
return this._customScheduler;
};
Async.prototype.haveItemsQueued = function () {
return this._isTickUsed || this._haveDrainedQueues;
};
Async.prototype.fatalError = function(e, isNode) {
if (isNode) {
process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) +
"\n");
process.exit(2);
} else {
this.throwLater(e);
}
};
// Must be used if fn can throw
Async.prototype.throwLater = function(fn, arg) {
if (arguments.length === 1) {
arg = fn;
fn = function () { throw arg; };
}
if (typeof setTimeout !== "undefined") {
setTimeout(function() {
fn(arg);
}, 0);
} else try {
this._schedule(function() {
fn(arg);
});
} catch (e) {
throw new Error(NO_ASYNC_SCHEDULER);
}
};
//When the fn absolutely needs to be called after
//the queue has been completely flushed
function AsyncInvokeLater(fn, receiver, arg) {
ASSERT(arguments.length === 3);
this._lateQueue.push(fn, receiver, arg);
this._queueTick();
}
function AsyncInvoke(fn, receiver, arg) {
ASSERT(arguments.length === 3);
this._normalQueue.push(fn, receiver, arg);
this._queueTick();
}
function AsyncSettlePromises(promise) {
this._normalQueue._pushOne(promise);
this._queueTick();
}
Async.prototype.invokeLater = AsyncInvokeLater;
Async.prototype.invoke = AsyncInvoke;
Async.prototype.settlePromises = AsyncSettlePromises;
function _drainQueue(queue) {
while (queue.length() > 0) {
_drainQueueStep(queue);
}
}
// Shift the queue in a separate function to allow
// garbage collection after each step
function _drainQueueStep(queue) {
var fn = queue.shift();
if (typeof fn !== "function") {
fn._settlePromises();
} else {
var receiver = queue.shift();
var arg = queue.shift();
fn.call(receiver, arg);
}
}
Async.prototype._drainQueues = function () {
ASSERT(this._isTickUsed);
_drainQueue(this._normalQueue);
this._reset();
this._haveDrainedQueues = true;
_drainQueue(this._lateQueue);
};
Async.prototype._queueTick = function () {
if (!this._isTickUsed) {
this._isTickUsed = true;
this._schedule(this.drainQueues);
}
};
Async.prototype._reset = function () {
this._isTickUsed = false;
};
module.exports = Async;
module.exports.firstLineError = firstLineError;
================================================
FILE: src/bind.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) {
var calledBind = false;
var rejectThis = function(_, e) {
this._reject(e);
};
var targetRejected = function(e, context) {
context.promiseRejectionQueued = true;
context.bindingPromise._then(rejectThis, rejectThis, null, this, e);
};
var bindingResolved = function(thisArg, context) {
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG, this._bitField)) {
this._resolveCallback(context.target);
}
};
var bindingRejected = function(e, context) {
if (!context.promiseRejectionQueued) this._reject(e);
};
Promise.prototype.bind = function (thisArg) {
if (!calledBind) {
calledBind = true;
Promise.prototype._propagateFrom = debug.propagateFromFunction();
Promise.prototype._boundValue = debug.boundValueFunction();
}
var maybePromise = tryConvertToPromise(thisArg);
var ret = new Promise(INTERNAL);
ret._propagateFrom(this, PROPAGATE_CANCEL);
var target = this._target();
ret._setBoundTo(maybePromise);
if (maybePromise instanceof Promise) {
var context = {
promiseRejectionQueued: false,
promise: ret,
target: target,
bindingPromise: maybePromise
};
target._then(INTERNAL, targetRejected, undefined, ret, context);
maybePromise._then(
bindingResolved, bindingRejected, undefined, ret, context);
ret._setOnCancel(maybePromise);
} else {
ret._resolveCallback(target);
}
return ret;
};
Promise.prototype._setBoundTo = function (obj) {
if (obj !== undefined) {
this._bitField = this._bitField | IS_BOUND;
this._boundTo = obj;
} else {
this._bitField = this._bitField & (~IS_BOUND);
}
};
Promise.prototype._isBound = function () {
return (this._bitField & IS_BOUND) === IS_BOUND;
};
Promise.bind = function (thisArg, value) {
return Promise.resolve(value).bind(thisArg);
};
};
================================================
FILE: src/bluebird.js
================================================
"use strict";
var old;
if (typeof Promise !== "undefined") old = Promise;
function noConflict() {
try { if (Promise === bluebird) Promise = old; }
catch (e) {}
return bluebird;
}
var bluebird = require("./promise")();
bluebird.noConflict = noConflict;
module.exports = bluebird;
================================================
FILE: src/call_get.js
================================================
"use strict";
var cr = Object.create;
if (cr) {
var callerCache = cr(null);
var getterCache = cr(null);
callerCache[" size"] = getterCache[" size"] = 0;
}
module.exports = function(Promise) {
var util = require("./util");
var canEvaluate = util.canEvaluate;
var isIdentifier = util.isIdentifier;
var getMethodCaller;
var getGetter;
if (!__BROWSER__) {
var makeMethodCaller = function (methodName) {
return new Function("ensureMethod", " \n\
return function(obj) { \n\
'use strict' \n\
var len = this.length; \n\
ensureMethod(obj, 'methodName'); \n\
switch(len) { \n\
case 1: return obj.methodName(this[0]); \n\
case 2: return obj.methodName(this[0], this[1]); \n\
case 3: return obj.methodName(this[0], this[1], this[2]); \n\
case 0: return obj.methodName(); \n\
default: \n\
return obj.methodName.apply(obj, this); \n\
} \n\
}; \n\
".replace(/methodName/g, methodName))(ensureMethod);
};
var makeGetter = function (propertyName) {
return new Function("obj", " \n\
'use strict'; \n\
return obj.propertyName; \n\
".replace("propertyName", propertyName));
};
var getCompiled = function(name, compiler, cache) {
var ret = cache[name];
if (typeof ret !== "function") {
if (!isIdentifier(name)) {
return null;
}
ret = compiler(name);
cache[name] = ret;
cache[" size"]++;
if (cache[" size"] > 512) {
var keys = Object.keys(cache);
for (var i = 0; i < 256; ++i) delete cache[keys[i]];
cache[" size"] = keys.length - 256;
}
}
return ret;
};
getMethodCaller = function(name) {
return getCompiled(name, makeMethodCaller, callerCache);
};
getGetter = function(name) {
return getCompiled(name, makeGetter, getterCache);
};
}
function ensureMethod(obj, methodName) {
var fn;
if (obj != null) fn = obj[methodName];
if (typeof fn !== "function") {
var message = "Object " + util.classString(obj) + " has no method '" +
util.toString(methodName) + "'";
throw new Promise.TypeError(message);
}
return fn;
}
function caller(obj) {
var methodName = this.pop();
var fn = ensureMethod(obj, methodName);
return fn.apply(obj, this);
}
Promise.prototype.call = function (methodName) {
INLINE_SLICE(args, arguments, 1);
if (!__BROWSER__) {
if (canEvaluate) {
var maybeCaller = getMethodCaller(methodName);
if (maybeCaller !== null) {
return this._then(
maybeCaller, undefined, undefined, args, undefined);
}
}
}
args.push(methodName);
return this._then(caller, undefined, undefined, args, undefined);
};
function namedGetter(obj) {
return obj[this];
}
function indexedGetter(obj) {
var index = +this;
if (index < 0) index = Math.max(0, index + obj.length);
return obj[index];
}
Promise.prototype.get = function (propertyName) {
var isIndex = (typeof propertyName === "number");
var getter;
if (!isIndex) {
if (canEvaluate) {
var maybeGetter = getGetter(propertyName);
getter = maybeGetter !== null ? maybeGetter : namedGetter;
} else {
getter = namedGetter;
}
} else {
getter = indexedGetter;
}
return this._then(getter, undefined, undefined, propertyName, undefined);
};
};
================================================
FILE: src/cancel.js
================================================
"use strict";
module.exports = function(Promise, PromiseArray, apiRejection, debug) {
var ASSERT = require("./assert");
var util = require("./util");
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
var async = Promise._async;
Promise.prototype["break"] = Promise.prototype.cancel = function() {
if (!debug.cancellation()) return this._warn("cancellation is disabled");
var promise = this;
var child = promise;
while (promise._isCancellable()) {
if (!promise._cancelBy(child)) {
if (child._isFollowing()) {
child._followee().cancel();
} else {
child._cancelBranched();
}
break;
}
var parent = promise._cancellationParent;
if (parent == null || !parent._isCancellable()) {
if (promise._isFollowing()) {
promise._followee().cancel();
} else {
promise._cancelBranched();
}
break;
} else {
if (promise._isFollowing()) promise._followee().cancel();
promise._setWillBeCancelled();
child = promise;
promise = parent;
}
}
};
Promise.prototype._branchHasCancelled = function() {
ASSERT(typeof this._branchesRemainingToCancel === "number");
this._branchesRemainingToCancel--;
};
Promise.prototype._enoughBranchesHaveCancelled = function() {
return this._branchesRemainingToCancel === undefined ||
this._branchesRemainingToCancel <= 0;
};
Promise.prototype._cancelBy = function(canceller) {
if (canceller === this) {
this._branchesRemainingToCancel = 0;
this._invokeOnCancel();
return true;
} else {
ASSERT(canceller._cancellationParent === this);
this._branchHasCancelled();
if (this._enoughBranchesHaveCancelled()) {
this._invokeOnCancel();
return true;
}
}
return false;
};
Promise.prototype._cancelBranched = function() {
if (this._enoughBranchesHaveCancelled()) {
this._cancel();
}
};
Promise.prototype._cancel = function() {
if (!this._isCancellable()) return;
ASSERT(!this._isFollowing());
this._setCancelled();
async.invoke(this._cancelPromises, this, undefined);
};
Promise.prototype._cancelPromises = function() {
if (this._length() > 0) this._settlePromises();
};
Promise.prototype._unsetOnCancel = function() {
ASSERT(this._isCancellable() || this._isCancelled());
this._onCancelField = undefined;
};
Promise.prototype._isCancellable = function() {
return this.isPending() && !this._isCancelled();
};
Promise.prototype.isCancellable = function() {
return this.isPending() && !this.isCancelled();
};
Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) {
if (util.isArray(onCancelCallback)) {
for (var i = 0; i < onCancelCallback.length; ++i) {
this._doInvokeOnCancel(onCancelCallback[i], internalOnly);
}
} else if (onCancelCallback !== undefined) {
if (typeof onCancelCallback === "function") {
if (!internalOnly) {
var e = tryCatch(onCancelCallback).call(this._boundValue());
if (e === errorObj) {
this._attachExtraTrace(e.e);
async.throwLater(e.e);
}
}
} else {
onCancelCallback._resultCancelled(this);
}
}
};
Promise.prototype._invokeOnCancel = function() {
var onCancelCallback = this._onCancel();
// The existence of onCancel handler on a promise signals that the handler
// has not been queued for invocation yet.
this._unsetOnCancel();
async.invoke(this._doInvokeOnCancel, this, onCancelCallback);
};
Promise.prototype._invokeInternalOnCancel = function() {
if (this._isCancellable()) {
this._doInvokeOnCancel(this._onCancel(), true);
this._unsetOnCancel();
}
};
Promise.prototype._resultCancelled = function() {
this.cancel();
};
};
================================================
FILE: src/catch_filter.js
================================================
"use strict";
module.exports = function(NEXT_FILTER) {
var util = require("./util");
var getKeys = require("./es5").keys;
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
function catchFilter(instances, cb, promise) {
return function(e) {
var boundTo = promise._boundValue();
predicateLoop: for (var i = 0; i < instances.length; ++i) {
var item = instances[i];
if (item === Error ||
(item != null && item.prototype instanceof Error)) {
if (e instanceof item) {
return tryCatch(cb).call(boundTo, e);
}
} else if (typeof item === "function") {
var matchesPredicate = tryCatch(item).call(boundTo, e);
if (matchesPredicate === errorObj) {
return matchesPredicate;
} else if (matchesPredicate) {
return tryCatch(cb).call(boundTo, e);
}
} else if (util.isObject(e)) {
var keys = getKeys(item);
for (var j = 0; j < keys.length; ++j) {
var key = keys[j];
if (item[key] != e[key]) {
continue predicateLoop;
}
}
return tryCatch(cb).call(boundTo, e);
}
}
return NEXT_FILTER;
};
}
return catchFilter;
};
================================================
FILE: src/constants.js
================================================
//This is pretty lame but what you gonna do
//async.js
CONSTANT(LATE_QUEUE_CAPACITY, 16);
CONSTANT(NORMAL_QUEUE_CAPACITY, 16);
//errors.js
CONSTANT(ERROR_HANDLED_KEY, "__promiseHandled__");
CONSTANT(OPERATIONAL_ERROR_KEY, "isOperational");
CONSTANT(DEFAULT_STATE, 0);
CONSTANT(STACK_ATTACHED, 1);
CONSTANT(ERROR_HANDLED, 2);
//join.js
CONSTANT(GENERATED_CLASS_COUNT, 8);
//promise.js
CONSTANT(USE_BOUND, true);
CONSTANT(DONT_USE_BOUND, false);
CONSTANT(PROPAGATE_CANCEL, 1);
CONSTANT(PROPAGATE_BIND, 2);
CONSTANT(PROPAGATE_ALL, PROPAGATE_CANCEL | PROPAGATE_BIND);
CONSTANT(CALLBACK_FULFILL_OFFSET, 0);
CONSTANT(CALLBACK_REJECT_OFFSET, 1);
CONSTANT(CALLBACK_PROMISE_OFFSET, 2);
CONSTANT(CALLBACK_RECEIVER_OFFSET, 3);
CONSTANT(CALLBACK_SIZE, 4);
//Layout for ._bitField
//[RR]XO GWFN CTBH IUDE LLLL LLLL LLLL LLLL
//[RR] = [Reserved] (Both bits are either on or off to represent
// 1 bit due to 31-bit integers in 32-bit v8)
//R = [Reserved]
//X = noAsyncGuarantee
//O = returnedNonUndefined
//G = isAsyncGuaranteed
//W = isFollowing (The promise that is being followed is not stored explicitly)
//F = isFulfilled
//N = isRejected
//C = willBeCancelled
//T = isFinal (used for .done() implementation)
//B = isBound
//I = isRejectionIgnored
//H = isRejectionUnhandled
//U = isUnhanldedRejectionNotified
//D = isDisposable
//E = isCancelled
//L = Length, 16 bit unsigned
CONSTANT(ASYNC_GUARANTEE_SHIFT, 2)
CONSTANT(NO_STATE, 0x0|0);
CONSTANT(NO_ASYNC_GUARANTEE, 0x20000000|0);
CONSTANT(RETURNED_NON_UNDEFINED, 0x10000000|0);
CONSTANT(IS_ASYNC_GUARANTEED, 0x8000000|0);
CONSTANT(IS_FOLLOWING, 0x4000000|0);
CONSTANT(IS_FULFILLED, 0x2000000|0);
CONSTANT(IS_REJECTED, 0x1000000|0);
CONSTANT(WILL_BE_CANCELLED, 0x800000|0);
CONSTANT(IS_FINAL, 0x400000|0);
CONSTANT(IS_BOUND, 0x200000|0);
CONSTANT(IS_REJECTION_UNHANDLED, 0x100000|0);
CONSTANT(IS_REJECTION_IGNORED, 0x80000|0);
CONSTANT(IS_UNHANDLED_REJECTION_NOTIFIED, 0x40000|0);
CONSTANT(IS_DISPOSABLE, 0x20000|0);
CONSTANT(IS_CANCELLED, 0x10000|0);
CONSTANT(IS_CANCELLED_OR_WILL_BE_CANCELLED, IS_CANCELLED | WILL_BE_CANCELLED)
CONSTANT(LENGTH_MASK, 0xFFFF|0);
CONSTANT(LENGTH_CLEAR_MASK, ~LENGTH_MASK);
CONSTANT(MAX_LENGTH, LENGTH_MASK);
CONSTANT(IS_REJECTED_OR_CANCELLED, IS_REJECTED | IS_CANCELLED);
CONSTANT(IS_REJECTED_OR_FULFILLED, IS_REJECTED | IS_FULFILLED);
CONSTANT(IS_REJECTED_OR_FULFILLED_OR_CANCELLED, IS_REJECTED | IS_FULFILLED| IS_CANCELLED);
CONSTANT(IS_PENDING_AND_WAITING_NEG, IS_REJECTED_OR_FULFILLED_OR_CANCELLED);
CONSTANT(IS_FATE_SEALED, IS_REJECTED | IS_FULFILLED | IS_FOLLOWING | IS_CANCELLED);
CONSTANT(AFTER_PROMISIFIED_SUFFIX, "Async");
CONSTANT(UNHANDLED_REJECTION_EVENT, "unhandledRejection");
CONSTANT(REJECTION_HANDLED_EVENT, "rejectionHandled");
//promise_array.js
//MUST BE NEGATIVE NUMBERS
CONSTANT(RESOLVE_UNDEFINED, -1);
CONSTANT(RESOLVE_ARRAY, -2);
CONSTANT(RESOLVE_OBJECT, -3);
CONSTANT(RESOLVE_FOREVER_PENDING, -4);
CONSTANT(RESOLVE_CALL_METHOD, -5);
CONSTANT(RESOLVE_MAP, -6);
//queue.js
CONSTANT(QUEUE_MAX_CAPACITY, (1 << 30) | 0);
CONSTANT(QUEUE_MIN_CAPACITY, 16);
//captured_trace.js
CONSTANT(FROM_PREVIOUS_EVENT, "From previous event:");
CONSTANT(NO_STACK_TRACE, " (No stack trace)");
CONSTANT(ADDITIONAL_STACK_TRACE, "^--- With additional stack trace: ");
CONSTANT(UNHANDLED_REJECTION_HEADER, "Unhandled rejection ");
//finally.js
CONSTANT(FINALLY_TYPE, 0);
CONSTANT(TAP_TYPE, 1);
//direct_resolve.js
CONSTANT(THROW, 1);
CONSTANT(RETURN, 2);
//promisify.js
CONSTANT(MAX_PARAM_COUNT, 1023);
CONSTANT(PARAM_COUNTS_TO_TRY, 3);
//error.js
CONSTANT(BLUEBIRD_ERRORS, "__BluebirdErrorTypes__");
//deprecated
CONSTANT(OBJECT_PROMISIFY_DEPRECATED, "Promise.promisify for promisifying entire objects is deprecated. Use Promise.promisifyAll instead.\n\n\
See http://goo.gl/MqrFmX");
CONSTANT(SPAWN_DEPRECATED, "Promise.spawn is deprecated. Use Promise.coroutine instead.");
//errors
CONSTANT(LATE_CANCELLATION_OBSERVER, "late cancellation observer");
CONSTANT(TIMEOUT_ERROR, "operation timed out");
CONSTANT(COLLECTION_ERROR, "expecting an array or an iterable object but got ");
CONSTANT(OBJECT_ERROR, "expecting an object but got ");
CONSTANT(FUNCTION_ERROR, "expecting a function but got ");
CONSTANT(CONSTRUCT_ERROR_INVOCATION, "the promise constructor cannot be invoked directly\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(NOT_GENERATOR_ERROR, "generatorFunction must be a function\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(LONG_STACK_TRACES_ERROR, "cannot enable long stack traces after promises have been created\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(INSPECTION_VALUE_ERROR, "cannot get fulfillment value of a non-fulfilled promise\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(INSPECTION_REASON_ERROR, "cannot get rejection reason of a non-rejected promise\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(PROMISIFY_TYPE_ERROR, "the target of promisifyAll must be an object or a function\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(CIRCULAR_RESOLUTION_ERROR, "circular promise resolution chain\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(PROPS_TYPE_ERROR, "cannot await properties of a non-object\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(POSITIVE_INTEGER_ERROR, "expecting a positive integer\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(YIELDED_NON_PROMISE_ERROR, "A value %s was yielded that could not be treated as a promise\n\n\
See http://goo.gl/MqrFmX\n\n");
CONSTANT(FROM_COROUTINE_CREATED_AT, "From coroutine:\n");
CONSTANT(UNBOUND_RESOLVER_INVOCATION, "Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(PROMISIFICATION_NORMAL_METHODS_ERROR, "Cannot promisify an API that has normal methods with '%s'-suffix\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(SUFFIX_NOT_IDENTIFIER, "suffix must be a valid identifier\n\n\
See http://goo.gl/MqrFmX\n");
CONSTANT(NO_ASYNC_SCHEDULER, "No async scheduler available\n\n\
See http://goo.gl/MqrFmX\n");
================================================
FILE: src/context.js
================================================
"use strict";
module.exports = function(Promise) {
var longStackTraces = false;
var contextStack = [];
Promise.prototype._promiseCreated = function() {};
Promise.prototype._pushContext = function() {};
Promise.prototype._popContext = function() {return null;};
Promise._peekContext = Promise.prototype._peekContext = function() {};
function Context() {
this._trace = new Context.CapturedTrace(peekContext());
}
Context.prototype._pushContext = function () {
if (this._trace !== undefined) {
this._trace._promiseCreated = null;
contextStack.push(this._trace);
}
};
Context.prototype._popContext = function () {
if (this._trace !== undefined) {
var trace = contextStack.pop();
var ret = trace._promiseCreated;
trace._promiseCreated = null;
return ret;
}
return null;
};
function createContext() {
if (longStackTraces) return new Context();
}
function peekContext() {
var lastIndex = contextStack.length - 1;
if (lastIndex >= 0) {
return contextStack[lastIndex];
}
return undefined;
}
Context.CapturedTrace = null;
Context.create = createContext;
Context.deactivateLongStackTraces = function() {};
Context.activateLongStackTraces = function() {
var Promise_pushContext = Promise.prototype._pushContext;
var Promise_popContext = Promise.prototype._popContext;
var Promise_PeekContext = Promise._peekContext;
var Promise_peekContext = Promise.prototype._peekContext;
var Promise_promiseCreated = Promise.prototype._promiseCreated;
Context.deactivateLongStackTraces = function() {
Promise.prototype._pushContext = Promise_pushContext;
Promise.prototype._popContext = Promise_popContext;
Promise._peekContext = Promise_PeekContext;
Promise.prototype._peekContext = Promise_peekContext;
Promise.prototype._promiseCreated = Promise_promiseCreated;
longStackTraces = false;
};
longStackTraces = true;
Promise.prototype._pushContext = Context.prototype._pushContext;
Promise.prototype._popContext = Context.prototype._popContext;
Promise._peekContext = Promise.prototype._peekContext = peekContext;
Promise.prototype._promiseCreated = function() {
var ctx = this._peekContext();
if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this;
};
};
return Context;
};
================================================
FILE: src/debuggability.js
================================================
"use strict";
module.exports = function(Promise, Context,
enableAsyncHooks, disableAsyncHooks) {
var async = Promise._async;
var Warning = require("./errors").Warning;
var util = require("./util");
var es5 = require("./es5");
var ASSERT = require("./assert");
var canAttachTrace = util.canAttachTrace;
var unhandledRejectionHandled;
var possiblyUnhandledRejection;
var bluebirdFramePattern =
/[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/;
var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/;
var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/;
var stackFramePattern = null;
var formatStack = null;
var indentStackFrames = false;
var printWarning;
var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 &&
(__DEBUG__ ||
util.env("BLUEBIRD_DEBUG") ||
util.env("NODE_ENV") === "development"));
var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 &&
(debugging || util.env("BLUEBIRD_WARNINGS")));
var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 &&
(debugging || util.env("BLUEBIRD_LONG_STACK_TRACES")));
var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 &&
(warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN"));
var deferUnhandledRejectionCheck;
(function() {
var promises = [];
function unhandledRejectionCheck() {
for (var i = 0; i < promises.length; ++i) {
promises[i]._notifyUnhandledRejection();
}
unhandledRejectionClear();
}
function unhandledRejectionClear() {
promises.length = 0;
}
deferUnhandledRejectionCheck = function(promise) {
promises.push(promise);
setTimeout(unhandledRejectionCheck, 1);
};
es5.defineProperty(Promise, "_unhandledRejectionCheck", {
value: unhandledRejectionCheck
});
es5.defineProperty(Promise, "_unhandledRejectionClear", {
value: unhandledRejectionClear
});
})();
Promise.prototype.suppressUnhandledRejections = function() {
var target = this._target();
target._bitField = ((target._bitField & (~IS_REJECTION_UNHANDLED)) |
IS_REJECTION_IGNORED);
};
Promise.prototype._ensurePossibleRejectionHandled = function () {
if ((this._bitField & IS_REJECTION_IGNORED) !== 0) return;
this._setRejectionIsUnhandled();
deferUnhandledRejectionCheck(this);
};
Promise.prototype._notifyUnhandledRejectionIsHandled = function () {
fireRejectionEvent(REJECTION_HANDLED_EVENT,
unhandledRejectionHandled, undefined, this);
};
Promise.prototype._setReturnedNonUndefined = function() {
this._bitField = this._bitField | RETURNED_NON_UNDEFINED;
};
Promise.prototype._returnedNonUndefined = function() {
return (this._bitField & RETURNED_NON_UNDEFINED) !== 0;
};
Promise.prototype._notifyUnhandledRejection = function () {
if (this._isRejectionUnhandled()) {
var reason = this._settledValue();
this._setUnhandledRejectionIsNotified();
fireRejectionEvent(UNHANDLED_REJECTION_EVENT,
possiblyUnhandledRejection, reason, this);
}
};
Promise.prototype._setUnhandledRejectionIsNotified = function () {
this._bitField = this._bitField | IS_UNHANDLED_REJECTION_NOTIFIED;
};
Promise.prototype._unsetUnhandledRejectionIsNotified = function () {
this._bitField = this._bitField & (~IS_UNHANDLED_REJECTION_NOTIFIED);
};
Promise.prototype._isUnhandledRejectionNotified = function () {
return (this._bitField & IS_UNHANDLED_REJECTION_NOTIFIED) > 0;
};
Promise.prototype._setRejectionIsUnhandled = function () {
ASSERT(!this._isFollowing());
this._bitField = this._bitField | IS_REJECTION_UNHANDLED;
};
Promise.prototype._unsetRejectionIsUnhandled = function () {
ASSERT(!this._isFollowing());
this._bitField = this._bitField & (~IS_REJECTION_UNHANDLED);
if (this._isUnhandledRejectionNotified()) {
this._unsetUnhandledRejectionIsNotified();
this._notifyUnhandledRejectionIsHandled();
}
};
Promise.prototype._isRejectionUnhandled = function () {
ASSERT(!this._isFollowing());
return (this._bitField & IS_REJECTION_UNHANDLED) > 0;
};
Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
return warn(message, shouldUseOwnTrace, promise || this);
};
Promise.onPossiblyUnhandledRejection = function (fn) {
var context = Promise._getContext();
possiblyUnhandledRejection = util.contextBind(context, fn);
};
Promise.onUnhandledRejectionHandled = function (fn) {
var context = Promise._getContext();
unhandledRejectionHandled = util.contextBind(context, fn);
};
var disableLongStackTraces = function() {};
Promise.longStackTraces = function () {
if (async.haveItemsQueued() && !config.longStackTraces) {
throw new Error(LONG_STACK_TRACES_ERROR);
}
if (!config.longStackTraces && longStackTracesIsSupported()) {
var Promise_captureStackTrace = Promise.prototype._captureStackTrace;
var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace;
var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace;
config.longStackTraces = true;
disableLongStackTraces = function() {
if (async.haveItemsQueued() && !config.longStackTraces) {
throw new Error(LONG_STACK_TRACES_ERROR);
}
Promise.prototype._captureStackTrace = Promise_captureStackTrace;
Promise.prototype._attachExtraTrace = Promise_attachExtraTrace;
Promise.prototype._dereferenceTrace = Promise_dereferenceTrace;
Context.deactivateLongStackTraces();
config.longStackTraces = false;
};
Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace;
Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace;
Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace;
Context.activateLongStackTraces();
}
};
Promise.hasLongStackTraces = function () {
return config.longStackTraces && longStackTracesIsSupported();
};
var legacyHandlers = {
unhandledrejection: {
before: function() {
var ret = util.global.onunhandledrejection;
util.global.onunhandledrejection = null;
return ret;
},
after: function(fn) {
util.global.onunhandledrejection = fn;
}
},
rejectionhandled: {
before: function() {
var ret = util.global.onrejectionhandled;
util.global.onrejectionhandled = null;
return ret;
},
after: function(fn) {
util.global.onrejectionhandled = fn;
}
}
};
var fireDomEvent = (function() {
var dispatch = function(legacy, e) {
if (legacy) {
var fn;
try {
fn = legacy.before();
return !util.global.dispatchEvent(e);
} finally {
legacy.after(fn);
}
} else {
return !util.global.dispatchEvent(e);
}
};
try {
if (typeof CustomEvent === "function") {
var event = new CustomEvent("CustomEvent");
util.global.dispatchEvent(event);
return function(name, event) {
name = name.toLowerCase();
var eventData = {
detail: event,
cancelable: true
};
var domEvent = new CustomEvent(name, eventData);
es5.defineProperty(
domEvent, "promise", {value: event.promise});
es5.defineProperty(
domEvent, "reason", {value: event.reason});
return dispatch(legacyHandlers[name], domEvent);
};
// In Firefox < 48 CustomEvent is not available in workers but
// Event is.
} else if (typeof Event === "function") {
var event = new Event("CustomEvent");
util.global.dispatchEvent(event);
return function(name, event) {
name = name.toLowerCase();
var domEvent = new Event(name, {
cancelable: true
});
domEvent.detail = event;
es5.defineProperty(domEvent, "promise", {value: event.promise});
es5.defineProperty(domEvent, "reason", {value: event.reason});
return dispatch(legacyHandlers[name], domEvent);
};
} else {
var event = document.createEvent("CustomEvent");
event.initCustomEvent("testingtheevent", false, true, {});
util.global.dispatchEvent(event);
return function(name, event) {
name = name.toLowerCase();
var domEvent = document.createEvent("CustomEvent");
domEvent.initCustomEvent(name, false, true,
event);
return dispatch(legacyHandlers[name], domEvent);
};
}
} catch (e) {}
return function() {
return false;
};
})();
var fireGlobalEvent = (function() {
if (util.isNode) {
return function() {
return process.emit.apply(process, arguments);
};
} else {
if (!util.global) {
return function() {
return false;
};
}
return function(name) {
var methodName = "on" + name.toLowerCase();
var method = util.global[methodName];
if (!method) return false;
method.apply(util.global, [].slice.call(arguments, 1));
return true;
};
}
})();
function generatePromiseLifecycleEventObject(name, promise) {
return {promise: promise};
}
var eventToObjectGenerator = {
promiseCreated: generatePromiseLifecycleEventObject,
promiseFulfilled: generatePromiseLifecycleEventObject,
promiseRejected: generatePromiseLifecycleEventObject,
promiseResolved: generatePromiseLifecycleEventObject,
promiseCancelled: generatePromiseLifecycleEventObject,
promiseChained: function(name, promise, child) {
return {promise: promise, child: child};
},
warning: function(name, warning) {
return {warning: warning};
},
unhandledRejection: function (name, reason, promise) {
return {reason: reason, promise: promise};
},
rejectionHandled: generatePromiseLifecycleEventObject
};
var activeFireEvent = function (name) {
var globalEventFired = false;
try {
globalEventFired = fireGlobalEvent.apply(null, arguments);
} catch (e) {
async.throwLater(e);
globalEventFired = true;
}
var domEventFired = false;
try {
domEventFired = fireDomEvent(name,
eventToObjectGenerator[name].apply(null, arguments));
} catch (e) {
async.throwLater(e);
domEventFired = true;
}
return domEventFired || globalEventFired;
};
Promise.config = function(opts) {
opts = Object(opts);
if ("longStackTraces" in opts) {
if (opts.longStackTraces) {
Promise.longStackTraces();
} else if (!opts.longStackTraces && Promise.hasLongStackTraces()) {
disableLongStackTraces();
}
}
if ("warnings" in opts) {
var warningsOption = opts.warnings;
config.warnings = !!warningsOption;
wForgottenReturn = config.warnings;
if (util.isObject(warningsOption)) {
if ("wForgottenReturn" in warningsOption) {
wForgottenReturn = !!warningsOption.wForgottenReturn;
}
}
}
if ("cancellation" in opts && opts.cancellation && !config.cancellation) {
if (async.haveItemsQueued()) {
throw new Error(
"cannot enable cancellation after promises are in use");
}
Promise.prototype._clearCancellationData =
cancellationClearCancellationData;
Promise.prototype._propagateFrom = cancellationPropagateFrom;
Promise.prototype._onCancel = cancellationOnCancel;
Promise.prototype._setOnCancel = cancellationSetOnCancel;
Promise.prototype._attachCancellationCallback =
cancellationAttachCancellationCallback;
Promise.prototype._execute = cancellationExecute;
propagateFromFunction = cancellationPropagateFrom;
config.cancellation = true;
}
if ("monitoring" in opts) {
if (opts.monitoring && !config.monitoring) {
config.monitoring = true;
Promise.prototype._fireEvent = activeFireEvent;
} else if (!opts.monitoring && config.monitoring) {
config.monitoring = false;
Promise.prototype._fireEvent = defaultFireEvent;
}
}
if ("asyncHooks" in opts && util.nodeSupportsAsyncResource) {
var prev = config.asyncHooks;
var cur = !!opts.asyncHooks;
if (prev !== cur) {
config.asyncHooks = cur;
if (cur) {
enableAsyncHooks();
} else {
disableAsyncHooks();
}
}
}
return Promise;
};
function defaultFireEvent() { return false; }
Promise.prototype._fireEvent = defaultFireEvent;
Promise.prototype._execute = function(executor, resolve, reject) {
try {
executor(resolve, reject);
} catch (e) {
return e;
}
};
Promise.prototype._onCancel = function () {};
Promise.prototype._setOnCancel = function (handler) { USE(handler); };
Promise.prototype._attachCancellationCallback = function(onCancel) {
USE(onCancel);
};
Promise.prototype._captureStackTrace = function () {};
Promise.prototype._attachExtraTrace = function () {};
Promise.prototype._dereferenceTrace = function () {};
Promise.prototype._clearCancellationData = function() {};
Promise.prototype._propagateFrom = function (parent, flags) {
USE(parent);
USE(flags);
};
function cancellationExecute(executor, resolve, reject) {
var promise = this;
try {
executor(resolve, reject, function(onCancel) {
if (typeof onCancel !== "function") {
throw new TypeError("onCancel must be a function, got: " +
util.toString(onCancel));
}
promise._attachCancellationCallback(onCancel);
});
} catch (e) {
return e;
}
}
function cancellationAttachCancellationCallback(onCancel) {
if (!this._isCancellable()) return this;
var previousOnCancel = this._onCancel();
if (previousOnCancel !== undefined) {
if (util.isArray(previousOnCancel)) {
previousOnCancel.push(onCancel);
} else {
this._setOnCancel([previousOnCancel, onCancel]);
}
} else {
this._setOnCancel(onCancel);
}
}
function cancellationOnCancel() {
ASSERT(this._isCancellable());
return this._onCancelField;
}
function cancellationSetOnCancel(onCancel) {
ASSERT(this._isCancellable());
this._onCancelField = onCancel;
}
function cancellationClearCancellationData() {
this._cancellationParent = undefined;
this._onCancelField = undefined;
}
function cancellationPropagateFrom(parent, flags) {
ASSERT(flags !== 0);
if ((flags & PROPAGATE_CANCEL) !== 0) {
this._cancellationParent = parent;
var branchesRemainingToCancel = parent._branchesRemainingToCancel;
if (branchesRemainingToCancel === undefined) {
branchesRemainingToCancel = 0;
}
parent._branchesRemainingToCancel = branchesRemainingToCancel + 1;
}
if ((flags & PROPAGATE_BIND) !== 0 && parent._isBound()) {
this._setBoundTo(parent._boundTo);
}
}
function bindingPropagateFrom(parent, flags) {
ASSERT(flags !== 0);
if ((flags & PROPAGATE_BIND) !== 0 && parent._isBound()) {
this._setBoundTo(parent._boundTo);
}
}
var propagateFromFunction = bindingPropagateFrom;
function boundValueFunction() {
var ret = this._boundTo;
if (ret !== undefined) {
if (ret instanceof Promise) {
if (ret.isFulfilled()) {
return ret.value();
} else {
return undefined;
}
}
}
return ret;
}
function longStackTracesCaptureStackTrace() {
ASSERT(this._trace == null);
this._trace = new CapturedTrace(this._peekContext());
}
function longStackTracesAttachExtraTrace(error, ignoreSelf) {
if (canAttachTrace(error)) {
var trace = this._trace;
if (trace !== undefined) {
if (ignoreSelf) trace = trace._parent;
}
if (trace !== undefined) {
trace.attachExtraTrace(error);
} else if (!error.__stackCleaned__) {
var parsed = parseStackAndMessage(error);
util.notEnumerableProp(error, "stack",
parsed.message + "\n" + parsed.stack.join("\n"));
util.notEnumerableProp(error, "__stackCleaned__", true);
}
}
}
function longStackTracesDereferenceTrace() {
this._trace = undefined;
}
function checkForgottenReturns(returnValue, promiseCreated, name, promise,
parent) {
if (returnValue === undefined && promiseCreated !== null &&
wForgottenReturn) {
if (parent !== undefined && parent._returnedNonUndefined()) return;
if (BIT_FIELD_READ(LENGTH_MASK, promise._bitField) === 0) return;
if (name) name = name + " ";
var handlerLine = "";
var creatorLine = "";
if (promiseCreated._trace) {
var traceLines = promiseCreated._trace.stack.split("\n");
var stack = cleanStack(traceLines);
for (var i = stack.length - 1; i >= 0; --i) {
var line = stack[i];
if (!nodeFramePattern.test(line)) {
var lineMatches = line.match(parseLinePattern);
if (lineMatches) {
handlerLine = "at " + lineMatches[1] +
":" + lineMatches[2] + ":" + lineMatches[3] + " ";
}
break;
}
}
if (stack.length > 0) {
var firstUserLine = stack[0];
for (var i = 0; i < traceLines.length; ++i) {
if (traceLines[i] === firstUserLine) {
if (i > 0) {
creatorLine = "\n" + traceLines[i - 1];
}
break;
}
}
}
}
var msg = "a promise was created in a " + name +
"handler " + handlerLine + "but was not returned from it, " +
"see http://goo.gl/rRqMUw" +
creatorLine;
promise._warn(msg, true, promiseCreated);
}
}
function deprecated(name, replacement) {
var message = name +
" is deprecated and will be removed in a future version.";
if (replacement) message += " Use " + replacement + " instead.";
return warn(message);
}
function warn(message, shouldUseOwnTrace, promise) {
if (!config.warnings) return;
var warning = new Warning(message);
var ctx;
if (shouldUseOwnTrace) {
promise._attachExtraTrace(warning);
} else if (config.longStackTraces && (ctx = Promise._peekContext())) {
ctx.attachExtraTrace(warning);
} else {
var parsed = parseStackAndMessage(warning);
warning.stack = parsed.message + "\n" + parsed.stack.join("\n");
}
if (!activeFireEvent("warning", warning)) {
formatAndLogError(warning, "", true);
}
}
function reconstructStack(message, stacks) {
for (var i = 0; i < stacks.length - 1; ++i) {
stacks[i].push(FROM_PREVIOUS_EVENT);
stacks[i] = stacks[i].join("\n");
}
if (i < stacks.length) {
stacks[i] = stacks[i].join("\n");
}
return message + "\n" + stacks.join("\n");
}
function removeDuplicateOrEmptyJumps(stacks) {
for (var i = 0; i < stacks.length; ++i) {
if (stacks[i].length === 0 ||
((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) {
stacks.splice(i, 1);
i--;
}
}
}
function removeCommonRoots(stacks) {
var current = stacks[0];
for (var i = 1; i < stacks.length; ++i) {
var prev = stacks[i];
var currentLastIndex = current.length - 1;
var currentLastLine = current[currentLastIndex];
var commonRootMeetPoint = -1;
for (var j = prev.length - 1; j >= 0; --j) {
if (prev[j] === currentLastLine) {
commonRootMeetPoint = j;
break;
}
}
for (var j = commonRootMeetPoint; j >= 0; --j) {
var line = prev[j];
if (current[currentLastIndex] === line) {
current.pop();
currentLastIndex--;
} else {
break;
}
}
current = prev;
}
}
function cleanStack(stack) {
var ret = [];
for (var i = 0; i < stack.length; ++i) {
var line = stack[i];
var isTraceLine = NO_STACK_TRACE === line ||
stackFramePattern.test(line);
var isInternalFrame = isTraceLine && shouldIgnore(line);
if (isTraceLine && !isInternalFrame) {
if (indentStackFrames && line.charAt(0) !== " ") {
// Make Firefox stack traces readable...it is almost
// impossible to see the event boundaries without
// indentation.
line = " " + line;
}
ret.push(line);
}
}
return ret;
}
function stackFramesAsArray(error) {
var stack = error.stack.replace(/\s+$/g, "").split("\n");
for (var i = 0; i < stack.length; ++i) {
var line = stack[i];
if (NO_STACK_TRACE === line || stackFramePattern.test(line)) {
break;
}
}
// Chrome and IE include the error message in the stack
if (i > 0 && error.name != "SyntaxError") {
stack = stack.slice(i);
}
return stack;
}
function parseStackAndMessage(error) {
var stack = error.stack;
var message = error.toString();
stack = typeof stack === "string" && stack.length > 0
? stackFramesAsArray(error) : [NO_STACK_TRACE];
return {
message: message,
stack: error.name == "SyntaxError" ? stack : cleanStack(stack)
};
}
function formatAndLogError(error, title, isSoft) {
if (typeof console !== "undefined") {
var message;
if (util.isObject(error)) {
var stack = error.stack;
message = title + formatStack(stack, error);
} else {
message = title + String(error);
}
if (typeof printWarning === "function") {
printWarning(message, isSoft);
} else if (typeof console.log === "function" ||
typeof console.log === "object") {
console.log(message);
}
}
}
function fireRejectionEvent(name, localHandler, reason, promise) {
var localEventFired = false;
try {
if (typeof localHandler === "function") {
localEventFired = true;
if (name === REJECTION_HANDLED_EVENT) {
localHandler(promise);
} else {
localHandler(reason, promise);
}
}
} catch (e) {
async.throwLater(e);
}
if (name === UNHANDLED_REJECTION_EVENT) {
if (!activeFireEvent(name, reason, promise) && !localEventFired) {
formatAndLogError(reason, UNHANDLED_REJECTION_HEADER);
}
} else {
activeFireEvent(name, promise);
}
}
function formatNonError(obj) {
var str;
if (typeof obj === "function") {
str = "[function " +
(obj.name || "anonymous") +
"]";
} else {
str = obj && typeof obj.toString === "function"
? obj.toString() : util.toString(obj);
var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
if (ruselessToString.test(str)) {
try {
var newStr = JSON.stringify(obj);
str = newStr;
}
catch(e) {
}
}
if (str.length === 0) {
str = "(empty array)";
}
}
return ("(<" + snip(str) + ">, no stack trace)");
}
function snip(str) {
var maxChars = 41;
if (str.length < maxChars) {
return str;
}
return str.substr(0, maxChars - 3) + "...";
}
function longStackTracesIsSupported() {
return typeof captureStackTrace === "function";
}
// For filtering out internal calls from stack traces
var shouldIgnore = function() { return false; };
var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;
function parseLineInfo(line) {
var matches = line.match(parseLineInfoRegex);
if (matches) {
return {
fileName: matches[1],
line: parseInt(matches[2], 10)
};
}
}
function setBounds(firstLineError, lastLineError) {
if (!longStackTracesIsSupported()) return;
var firstStackLines = (firstLineError.stack || "").split("\n");
var lastStackLines = (lastLineError.stack || "").split("\n");
var firstIndex = -1;
var lastIndex = -1;
var firstFileName;
var lastFileName;
for (var i = 0; i < firstStackLines.length; ++i) {
var result = parseLineInfo(firstStackLines[i]);
if (result) {
firstFileName = result.fileName;
firstIndex = result.line;
break;
}
}
for (var i = 0; i < lastStackLines.length; ++i) {
var result = parseLineInfo(lastStackLines[i]);
if (result) {
lastFileName = result.fileName;
lastIndex = result.line;
break;
}
}
if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName ||
firstFileName !== lastFileName || firstIndex >= lastIndex) {
return;
}
shouldIgnore = function(line) {
if (bluebirdFramePattern.test(line)) return true;
var info = parseLineInfo(line);
if (info) {
if (info.fileName === firstFileName &&
(firstIndex <= info.line && info.line <= lastIndex)) {
return true;
}
}
return false;
};
}
function CapturedTrace(parent) {
ASSERT(parent === undefined || parent instanceof CapturedTrace);
this._parent = parent;
this._promisesCreated = 0;
var length = this._length = 1 + (parent === undefined ? 0 : parent._length);
captureStackTrace(this, CapturedTrace);
// Unless the user manually nested > 32 indentation levels,
// there must be cycles
if (length > 32) this.uncycle();
}
util.inherits(CapturedTrace, Error);
Context.CapturedTrace = CapturedTrace;
CapturedTrace.prototype.uncycle = function() {
var length = this._length;
if (length < 2) return;
var nodes = [];
var stackToIndex = {};
for (var i = 0, node = this; node !== undefined; ++i) {
nodes.push(node);
node = node._parent;
}
// the node length is only used as heuristic to decide when to decycle, as
// there may be multiple linked lists that share members and decycling one
// will fail to update lenghts in the other. This is the correct length.
length = this._length = i;
ASSERT(nodes[0] === this);
ASSERT(nodes[nodes.length - 1] instanceof CapturedTrace);
for (var i = length - 1; i >= 0; --i) {
var stack = nodes[i].stack;
if (stackToIndex[stack] === undefined) {
stackToIndex[stack] = i;
}
}
for (var i = 0; i < length; ++i) {
var currentStack = nodes[i].stack;
var index = stackToIndex[currentStack];
ASSERT(currentStack === nodes[index].stack);
if (index !== undefined && index !== i) {
if (index > 0) {
ASSERT(nodes[index - 1]._parent === nodes[index]);
nodes[index - 1]._parent = undefined;
nodes[index - 1]._length = 1;
}
nodes[i]._parent = undefined;
nodes[i]._length = 1;
var cycleEdgeNode = i > 0 ? nodes[i - 1] : this;
if (index < length - 1) {
cycleEdgeNode._parent = nodes[index + 1];
cycleEdgeNode._parent.uncycle();
cycleEdgeNode._length =
cycleEdgeNode._parent._length + 1;
} else {
cycleEdgeNode._parent = undefined;
cycleEdgeNode._length = 1;
}
var currentChildLength = cycleEdgeNode._length + 1;
for (var j = i - 2; j >= 0; --j) {
nodes[j]._length = currentChildLength;
currentChildLength++;
}
return;
}
}
};
CapturedTrace.prototype.attachExtraTrace = function(error) {
if (error.__stackCleaned__) return;
this.uncycle();
var parsed = parseStackAndMessage(error);
var message = parsed.message;
var stacks = [parsed.stack];
var trace = this;
while (trace !== undefined) {
stacks.push(cleanStack(trace.stack.split("\n")));
trace = trace._parent;
}
removeCommonRoots(stacks);
removeDuplicateOrEmptyJumps(stacks);
util.notEnumerableProp(error, "stack", reconstructStack(message, stacks));
util.notEnumerableProp(error, "__stackCleaned__", true);
};
var captureStackTrace = (function stackDetection() {
var v8stackFramePattern = /^\s*at\s*/;
var v8stackFormatter = function(stack, error) {
ASSERT(error !== null);
if (typeof stack === "string") return stack;
if (error.name !== undefined &&
error.message !== undefined) {
return error.toString();
}
return formatNonError(error);
};
//V8
if (typeof Error.stackTraceLimit === "number" &&
typeof Error.captureStackTrace === "function") {
Error.stackTraceLimit += 6;
stackFramePattern = v8stackFramePattern;
formatStack = v8stackFormatter;
var captureStackTrace = Error.captureStackTrace;
// For node
shouldIgnore = function(line) {
return bluebirdFramePattern.test(line);
};
return function(receiver, ignoreUntil) {
Error.stackTraceLimit += 6;
captureStackTrace(receiver, ignoreUntil);
Error.stackTraceLimit -= 6;
};
}
var err = new Error();
//SpiderMonkey
if (typeof err.stack === "string" &&
err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) {
stackFramePattern = /@/;
formatStack = v8stackFormatter;
indentStackFrames = true;
return function captureStackTrace(o) {
o.stack = new Error().stack;
};
}
var hasStackAfterThrow;
try { throw new Error(); }
catch(e) {
hasStackAfterThrow = ("stack" in e);
}
// IE 10+
if (!("stack" in err) && hasStackAfterThrow &&
typeof Error.stackTraceLimit === "number") {
stackFramePattern = v8stackFramePattern;
formatStack = v8stackFormatter;
return function captureStackTrace(o) {
Error.stackTraceLimit += 6;
try { throw new Error(); }
catch(e) { o.stack = e.stack; }
Error.stackTraceLimit -= 6;
};
}
formatStack = function(stack, error) {
if (typeof stack === "string") return stack;
if ((typeof error === "object" ||
typeof error === "function") &&
error.name !== undefined &&
error.message !== undefined) {
return error.toString();
}
return formatNonError(error);
};
return null;
})([]);
if (typeof console !== "undefined" && typeof console.warn !== "undefined") {
printWarning = function (message) {
console.warn(message);
};
if (util.isNode && process.stderr.isTTY) {
printWarning = function(message, isSoft) {
var color = isSoft ? "\u001b[33m" : "\u001b[31m";
console.warn(color + message + "\u001b[0m\n");
};
} else if (!util.isNode && typeof (new Error().stack) === "string") {
printWarning = function(message, isSoft) {
console.warn("%c" + message,
isSoft ? "color: darkorange" : "color: red");
};
}
}
var config = {
warnings: warnings,
longStackTraces: false,
cancellation: false,
monitoring: false,
asyncHooks: false
};
if (longStackTraces) Promise.longStackTraces();
return {
asyncHooks: function() {
return config.asyncHooks;
},
longStackTraces: function() {
return config.longStackTraces;
},
warnings: function() {
return config.warnings;
},
cancellation: function() {
return config.cancellation;
},
monitoring: function() {
return config.monitoring;
},
propagateFromFunction: function() {
return propagateFromFunction;
},
boundValueFunction: function() {
return boundValueFunction;
},
checkForgottenReturns: checkForgottenReturns,
setBounds: setBounds,
warn: warn,
deprecated: deprecated,
CapturedTrace: CapturedTrace,
fireDomEvent: fireDomEvent,
fireGlobalEvent: fireGlobalEvent
};
};
================================================
FILE: src/direct_resolve.js
================================================
"use strict";
module.exports = function(Promise) {
function returner() {
return this.value;
}
function thrower() {
throw this.reason;
}
Promise.prototype["return"] =
Promise.prototype.thenReturn = function (value) {
if (value instanceof Promise) value.suppressUnhandledRejections();
return this._then(
returner, undefined, undefined, {value: value}, undefined);
};
Promise.prototype["throw"] =
Promise.prototype.thenThrow = function (reason) {
return this._then(
thrower, undefined, undefined, {reason: reason}, undefined);
};
Promise.prototype.catchThrow = function (reason) {
if (arguments.length <= 1) {
return this._then(
undefined, thrower, undefined, {reason: reason}, undefined);
} else {
var _reason = arguments[1];
var handler = function() {throw _reason;};
return this.caught(reason, handler);
}
};
Promise.prototype.catchReturn = function (value) {
if (arguments.length <= 1) {
if (value instanceof Promise) value.suppressUnhandledRejections();
return this._then(
undefined, returner, undefined, {value: value}, undefined);
} else {
var _value = arguments[1];
if (_value instanceof Promise) _value.suppressUnhandledRejections();
var handler = function() {return _value;};
return this.caught(value, handler);
}
};
};
================================================
FILE: src/each.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL) {
var PromiseReduce = Promise.reduce;
var PromiseAll = Promise.all;
function promiseAllThis() {
return PromiseAll(this);
}
function PromiseMapSeries(promises, fn) {
return PromiseReduce(promises, fn, INTERNAL, INTERNAL);
}
Promise.prototype.each = function (fn) {
return PromiseReduce(this, fn, INTERNAL, 0)
._then(promiseAllThis, undefined, undefined, this, undefined);
};
Promise.prototype.mapSeries = function (fn) {
return PromiseReduce(this, fn, INTERNAL, INTERNAL);
};
Promise.each = function (promises, fn) {
return PromiseReduce(promises, fn, INTERNAL, 0)
._then(promiseAllThis, undefined, undefined, promises, undefined);
};
Promise.mapSeries = PromiseMapSeries;
};
================================================
FILE: src/errors.js
================================================
"use strict";
var es5 = require("./es5");
var Objectfreeze = es5.freeze;
var util = require("./util");
var inherits = util.inherits;
var notEnumerableProp = util.notEnumerableProp;
function subError(nameProperty, defaultMessage) {
function SubError(message) {
if (!(this instanceof SubError)) return new SubError(message);
notEnumerableProp(this, "message",
typeof message === "string" ? message : defaultMessage);
notEnumerableProp(this, "name", nameProperty);
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
} else {
Error.call(this);
}
}
inherits(SubError, Error);
return SubError;
}
var _TypeError, _RangeError;
var Warning = subError("Warning", "warning");
var CancellationError = subError("CancellationError", "cancellation error");
var TimeoutError = subError("TimeoutError", "timeout error");
var AggregateError = subError("AggregateError", "aggregate error");
try {
_TypeError = TypeError;
_RangeError = RangeError;
} catch(e) {
_TypeError = subError("TypeError", "type error");
_RangeError = subError("RangeError", "range error");
}
var methods = ("join pop push shift unshift slice filter forEach some " +
"every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" ");
for (var i = 0; i < methods.length; ++i) {
if (typeof Array.prototype[methods[i]] === "function") {
AggregateError.prototype[methods[i]] = Array.prototype[methods[i]];
}
}
es5.defineProperty(AggregateError.prototype, "length", {
value: 0,
configurable: false,
writable: true,
enumerable: true
});
AggregateError.prototype[OPERATIONAL_ERROR_KEY] = true;
var level = 0;
AggregateError.prototype.toString = function() {
var indent = Array(level * 4 + 1).join(" ");
var ret = "\n" + indent + "AggregateError of:" + "\n";
level++;
indent = Array(level * 4 + 1).join(" ");
for (var i = 0; i < this.length; ++i) {
var str = this[i] === this ? "[Circular AggregateError]" : this[i] + "";
var lines = str.split("\n");
for (var j = 0; j < lines.length; ++j) {
lines[j] = indent + lines[j];
}
str = lines.join("\n");
ret += str + "\n";
}
level--;
return ret;
};
function OperationalError(message) {
if (!(this instanceof OperationalError))
return new OperationalError(message);
notEnumerableProp(this, "name", "OperationalError");
notEnumerableProp(this, "message", message);
this.cause = message;
this[OPERATIONAL_ERROR_KEY] = true;
if (message instanceof Error) {
notEnumerableProp(this, "message", message.message);
notEnumerableProp(this, "stack", message.stack);
} else if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
inherits(OperationalError, Error);
//Ensure all copies of the library throw the same error types
var errorTypes = Error[BLUEBIRD_ERRORS];
if (!errorTypes) {
errorTypes = Objectfreeze({
CancellationError: CancellationError,
TimeoutError: TimeoutError,
OperationalError: OperationalError,
RejectionError: OperationalError,
AggregateError: AggregateError
});
es5.defineProperty(Error, BLUEBIRD_ERRORS, {
value: errorTypes,
writable: false,
enumerable: false,
configurable: false
});
}
module.exports = {
Error: Error,
TypeError: _TypeError,
RangeError: _RangeError,
CancellationError: errorTypes.CancellationError,
OperationalError: errorTypes.OperationalError,
TimeoutError: errorTypes.TimeoutError,
AggregateError: errorTypes.AggregateError,
Warning: Warning
};
================================================
FILE: src/es5.js
================================================
var isES5 = (function(){
"use strict";
return this === undefined;
})();
if (isES5) {
module.exports = {
freeze: Object.freeze,
defineProperty: Object.defineProperty,
getDescriptor: Object.getOwnPropertyDescriptor,
keys: Object.keys,
names: Object.getOwnPropertyNames,
getPrototypeOf: Object.getPrototypeOf,
isArray: Array.isArray,
isES5: isES5,
propertyIsWritable: function(obj, prop) {
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
return !!(!descriptor || descriptor.writable || descriptor.set);
}
};
} else {
var has = {}.hasOwnProperty;
var str = {}.toString;
var proto = {}.constructor.prototype;
var ObjectKeys = function (o) {
var ret = [];
for (var key in o) {
if (has.call(o, key)) {
ret.push(key);
}
}
return ret;
};
var ObjectGetDescriptor = function(o, key) {
return {value: o[key]};
};
var ObjectDefineProperty = function (o, key, desc) {
o[key] = desc.value;
return o;
};
var ObjectFreeze = function (obj) {
return obj;
};
var ObjectGetPrototypeOf = function (obj) {
try {
return Object(obj).constructor.prototype;
}
catch (e) {
return proto;
}
};
var ArrayIsArray = function (obj) {
try {
return str.call(obj) === "[object Array]";
}
catch(e) {
return false;
}
};
module.exports = {
isArray: ArrayIsArray,
keys: ObjectKeys,
names: ObjectKeys,
defineProperty: ObjectDefineProperty,
getDescriptor: ObjectGetDescriptor,
freeze: ObjectFreeze,
getPrototypeOf: ObjectGetPrototypeOf,
isES5: isES5,
propertyIsWritable: function() {
return true;
}
};
}
================================================
FILE: src/filter.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL) {
var PromiseMap = Promise.map;
Promise.prototype.filter = function (fn, options) {
return PromiseMap(this, fn, options, INTERNAL);
};
Promise.filter = function (promises, fn, options) {
return PromiseMap(promises, fn, options, INTERNAL);
};
};
================================================
FILE: src/finally.js
================================================
"use strict";
module.exports = function(Promise, tryConvertToPromise, NEXT_FILTER) {
var util = require("./util");
var CancellationError = Promise.CancellationError;
var errorObj = util.errorObj;
var catchFilter = require("./catch_filter")(NEXT_FILTER);
function PassThroughHandlerContext(promise, type, handler) {
this.promise = promise;
this.type = type;
this.handler = handler;
this.called = false;
this.cancelPromise = null;
}
PassThroughHandlerContext.prototype.isFinallyHandler = function() {
return this.type === FINALLY_TYPE;
};
function FinallyHandlerCancelReaction(finallyHandler) {
this.finallyHandler = finallyHandler;
}
FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
checkCancel(this.finallyHandler);
};
function checkCancel(ctx, reason) {
if (ctx.cancelPromise != null) {
if (arguments.length > 1) {
ctx.cancelPromise._reject(reason);
} else {
ctx.cancelPromise._cancel();
}
ctx.cancelPromise = null;
return true;
}
return false;
}
function succeed() {
return finallyHandler.call(this, this.promise._target()._settledValue());
}
function fail(reason) {
if (checkCancel(this, reason)) return;
errorObj.e = reason;
return errorObj;
}
function finallyHandler(reasonOrValue) {
var promise = this.promise;
var handler = this.handler;
if (!this.called) {
this.called = true;
var ret = this.isFinallyHandler()
? handler.call(promise._boundValue())
: handler.call(promise._boundValue(), reasonOrValue);
if (ret === NEXT_FILTER) {
return ret;
} else if (ret !== undefined) {
promise._setReturnedNonUndefined();
var maybePromise = tryConvertToPromise(ret, promise);
if (maybePromise instanceof Promise) {
if (this.cancelPromise != null) {
if (maybePromise._isCancelled()) {
var reason =
new CancellationError(LATE_CANCELLATION_OBSERVER);
promise._attachExtraTrace(reason);
errorObj.e = reason;
return errorObj;
} else if (maybePromise.isPending()) {
maybePromise._attachCancellationCallback(
new FinallyHandlerCancelReaction(this));
}
}
return maybePromise._then(
succeed, fail, undefined, this, undefined);
}
}
}
if (promise.isRejected()) {
checkCancel(this);
errorObj.e = reasonOrValue;
return errorObj;
} else {
checkCancel(this);
return reasonOrValue;
}
}
Promise.prototype._passThrough = function(handler, type, success, fail) {
if (typeof handler !== "function") return this.then();
return this._then(success,
fail,
undefined,
new PassThroughHandlerContext(this, type, handler),
undefined);
};
Promise.prototype.lastly =
Promise.prototype["finally"] = function (handler) {
return this._passThrough(handler,
FINALLY_TYPE,
finallyHandler,
finallyHandler);
};
Promise.prototype.tap = function (handler) {
return this._passThrough(handler, TAP_TYPE, finallyHandler);
};
Promise.prototype.tapCatch = function (handlerOrPredicate) {
var len = arguments.length;
if(len === 1) {
return this._passThrough(handlerOrPredicate,
TAP_TYPE,
undefined,
finallyHandler);
} else {
var catchInstances = new Array(len - 1),
j = 0, i;
for (i = 0; i < len - 1; ++i) {
var item = arguments[i];
if (util.isObject(item)) {
catchInstances[j++] = item;
} else {
return Promise.reject(new TypeError(
"tapCatch statement predicate: "
+ OBJECT_ERROR + util.classString(item)
));
}
}
catchInstances.length = j;
var handler = arguments[i];
return this._passThrough(catchFilter(catchInstances, handler, this),
TAP_TYPE,
undefined,
finallyHandler);
}
};
return PassThroughHandlerContext;
};
================================================
FILE: src/generators.js
================================================
"use strict";
module.exports = function(Promise,
apiRejection,
INTERNAL,
tryConvertToPromise,
Proxyable,
debug) {
var errors = require("./errors");
var TypeError = errors.TypeError;
var ASSERT = require("./assert");
var util = require("./util");
var errorObj = util.errorObj;
var tryCatch = util.tryCatch;
var yieldHandlers = [];
function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
for (var i = 0; i < yieldHandlers.length; ++i) {
traceParent._pushContext();
var result = tryCatch(yieldHandlers[i])(value);
traceParent._popContext();
if (result === errorObj) {
traceParent._pushContext();
var ret = Promise.reject(errorObj.e);
traceParent._popContext();
return ret;
}
var maybePromise = tryConvertToPromise(result, traceParent);
if (maybePromise instanceof Promise) return maybePromise;
}
return null;
}
function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
if (debug.cancellation()) {
var internal = new Promise(INTERNAL);
var _finallyPromise = this._finallyPromise = new Promise(INTERNAL);
this._promise = internal.lastly(function() {
return _finallyPromise;
});
internal._captureStackTrace();
internal._setOnCancel(this);
} else {
var promise = this._promise = new Promise(INTERNAL);
promise._captureStackTrace();
}
this._stack = stack;
this._generatorFunction = generatorFunction;
this._receiver = receiver;
this._generator = undefined;
this._yieldHandlers = typeof yieldHandler === "function"
? [yieldHandler].concat(yieldHandlers)
: yieldHandlers;
this._yieldedPromise = null;
this._cancellationPhase = false;
}
util.inherits(PromiseSpawn, Proxyable);
PromiseSpawn.prototype._isResolved = function() {
return this._promise === null;
};
PromiseSpawn.prototype._cleanup = function() {
this._promise = this._generator = null;
if (debug.cancellation() && this._finallyPromise !== null) {
this._finallyPromise._fulfill();
this._finallyPromise = null;
}
};
PromiseSpawn.prototype._promiseCancelled = function() {
if (this._isResolved()) return;
var implementsReturn = typeof this._generator["return"] !== "undefined";
var result;
if (!implementsReturn) {
var reason = new Promise.CancellationError(
"generator .return() sentinel");
Promise.coroutine.returnSentinel = reason;
this._promise._attachExtraTrace(reason);
this._promise._pushContext();
result = tryCatch(this._generator["throw"]).call(this._generator,
reason);
this._promise._popContext();
} else {
this._promise._pushContext();
result = tryCatch(this._generator["return"]).call(this._generator,
undefined);
this._promise._popContext();
}
this._cancellationPhase = true;
this._yieldedPromise = null;
this._continue(result);
};
PromiseSpawn.prototype._promiseFulfilled = function(value) {
this._yieldedPromise = null;
this._promise._pushContext();
var result = tryCatch(this._generator.next).call(this._generator, value);
this._promise._popContext();
this._continue(result);
};
PromiseSpawn.prototype._promiseRejected = function(reason) {
this._yieldedPromise = null;
this._promise._attachExtraTrace(reason);
this._promise._pushContext();
var result = tryCatch(this._generator["throw"])
.call(this._generator, reason);
this._promise._popContext();
this._continue(result);
};
PromiseSpawn.prototype._resultCancelled = function() {
if (this._yieldedPromise instanceof Promise) {
var promise = this._yieldedPromise;
this._yieldedPromise = null;
promise.cancel();
}
};
PromiseSpawn.prototype.promise = function () {
return this._promise;
};
PromiseSpawn.prototype._run = function () {
this._generator = this._generatorFunction.call(this._receiver);
this._receiver =
this._generatorFunction = undefined;
this._promiseFulfilled(undefined);
};
PromiseSpawn.prototype._continue = function (result) {
ASSERT(this._yieldedPromise == null);
var promise = this._promise;
if (result === errorObj) {
this._cleanup();
if (this._cancellationPhase) {
return promise.cancel();
} else {
return promise._rejectCallback(result.e, false);
}
}
var value = result.value;
if (result.done === true) {
this._cleanup();
if (this._cancellationPhase) {
return promise.cancel();
} else {
return promise._resolveCallback(value);
}
} else {
var maybePromise = tryConvertToPromise(value, this._promise);
if (!(maybePromise instanceof Promise)) {
maybePromise =
promiseFromYieldHandler(maybePromise,
this._yieldHandlers,
this._promise);
ASSERT(maybePromise === null || maybePromise instanceof Promise);
if (maybePromise === null) {
this._promiseRejected(
new TypeError(
YIELDED_NON_PROMISE_ERROR.replace("%s", String(value)) +
FROM_COROUTINE_CREATED_AT +
this._stack.split("\n").slice(1, -7).join("\n")
)
);
return;
}
}
maybePromise = maybePromise._target();
var bitField = maybePromise._bitField;
USE(bitField);
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
this._yieldedPromise = maybePromise;
maybePromise._proxy(this, null);
} else if (BIT_FIELD_CHECK(IS_FULFILLED)) {
Promise._async.invoke(
this._promiseFulfilled, this, maybePromise._value()
);
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
Promise._async.invoke(
this._promiseRejected, this, maybePromise._reason()
);
} else {
this._promiseCancelled();
}
}
};
Promise.coroutine = function (generatorFunction, options) {
//Throw synchronously because Promise.coroutine is semantically
//something you call at "compile time" to annotate static functions
if (typeof generatorFunction !== "function") {
throw new TypeError(NOT_GENERATOR_ERROR);
}
var yieldHandler = Object(options).yieldHandler;
var PromiseSpawn$ = PromiseSpawn;
var stack = new Error().stack;
return function () {
var generator = generatorFunction.apply(this, arguments);
var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
stack);
var ret = spawn.promise();
spawn._generator = generator;
spawn._promiseFulfilled(undefined);
return ret;
};
};
Promise.coroutine.addYieldHandler = function(fn) {
if (typeof fn !== "function") {
throw new TypeError(FUNCTION_ERROR + util.classString(fn));
}
yieldHandlers.push(fn);
};
Promise.spawn = function (generatorFunction) {
debug.deprecated("Promise.spawn()", "Promise.coroutine()");
//Return rejected promise because Promise.spawn is semantically
//something that will be called at runtime with possibly dynamic values
if (typeof generatorFunction !== "function") {
return apiRejection(NOT_GENERATOR_ERROR);
}
var spawn = new PromiseSpawn(generatorFunction, this);
var ret = spawn.promise();
spawn._run(Promise.spawn);
return ret;
};
};
================================================
FILE: src/join.js
================================================
"use strict";
module.exports =
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async) {
var util = require("./util");
var canEvaluate = util.canEvaluate;
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
var reject;
if (!__BROWSER__) {
if (canEvaluate) {
var thenCallback = function(i) {
return new Function("value", "holder", " \n\
'use strict'; \n\
holder.pIndex = value; \n\
holder.checkFulfillment(this); \n\
".replace(/Index/g, i));
};
var promiseSetter = function(i) {
return new Function("promise", "holder", " \n\
'use strict'; \n\
holder.pIndex = promise; \n\
".replace(/Index/g, i));
};
var generateHolderClass = function(total) {
var props = new Array(total);
for (var i = 0; i < props.length; ++i) {
props[i] = "this.p" + (i+1);
}
var assignment = props.join(" = ") + " = null;";
var cancellationCode= "var promise;\n" + props.map(function(prop) {
return " \n\
promise = " + prop + "; \n\
if (promise instanceof Promise) { \n\
promise.cancel(); \n\
} \n\
";
}).join("\n");
var passedArguments = props.join(", ");
var name = "Holder$" + total;
var code = "return function(tryCatch, errorObj, Promise, async) { \n\
'use strict'; \n\
function [TheName](fn) { \n\
[TheProperties] \n\
this.fn = fn; \n\
this.asyncNeeded = true; \n\
this.now = 0; \n\
} \n\
\n\
[TheName].prototype._callFunction = function(promise) { \n\
promise._pushContext(); \n\
var ret = tryCatch(this.fn)([ThePassedArguments]); \n\
promise._popContext(); \n\
if (ret === errorObj) { \n\
promise._rejectCallback(ret.e, false); \n\
} else { \n\
promise._resolveCallback(ret); \n\
} \n\
}; \n\
\n\
[TheName].prototype.checkFulfillment = function(promise) { \n\
var now = ++this.now; \n\
if (now === [TheTotal]) { \n\
if (this.asyncNeeded) { \n\
async.invoke(this._callFunction, this, promise); \n\
} else { \n\
this._callFunction(promise); \n\
} \n\
\n\
} \n\
}; \n\
\n\
[TheName].prototype._resultCancelled = function() { \n\
[CancellationCode] \n\
}; \n\
\n\
return [TheName]; \n\
}(tryCatch, errorObj, Promise, async); \n\
";
code = code.replace(/\[TheName\]/g, name)
.replace(/\[TheTotal\]/g, total)
.replace(/\[ThePassedArguments\]/g, passedArguments)
.replace(/\[TheProperties\]/g, assignment)
.replace(/\[CancellationCode\]/g, cancellationCode);
return new Function("tryCatch", "errorObj", "Promise", "async", code)
(tryCatch, errorObj, Promise, async);
};
var holderClasses = [];
var thenCallbacks = [];
var promiseSetters = [];
for (var i = 0; i < GENERATED_CLASS_COUNT; ++i) {
holderClasses.push(generateHolderClass(i + 1));
thenCallbacks.push(thenCallback(i + 1));
promiseSetters.push(promiseSetter(i + 1));
}
reject = function (reason) {
this._reject(reason);
};
}}
Promise.join = function () {
var last = arguments.length - 1;
var fn;
if (last > 0 && typeof arguments[last] === "function") {
fn = arguments[last];
if (!__BROWSER__) {
if (last <= GENERATED_CLASS_COUNT && canEvaluate) {
var ret = new Promise(INTERNAL);
ret._captureStackTrace();
var HolderClass = holderClasses[last - 1];
var holder = new HolderClass(fn);
var callbacks = thenCallbacks;
for (var i = 0; i < last; ++i) {
var maybePromise = tryConvertToPromise(arguments[i], ret);
if (maybePromise instanceof Promise) {
maybePromise = maybePromise._target();
var bitField = maybePromise._bitField;
USE(bitField);
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
maybePromise._then(callbacks[i], reject,
undefined, ret, holder);
promiseSetters[i](maybePromise, holder);
holder.asyncNeeded = false;
} else if (BIT_FIELD_CHECK(IS_FULFILLED)) {
callbacks[i].call(ret,
maybePromise._value(), holder);
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
ret._reject(maybePromise._reason());
} else {
ret._cancel();
}
} else {
callbacks[i].call(ret, maybePromise, holder);
}
}
if (!ret._isFateSealed()) {
if (holder.asyncNeeded) {
var context = Promise._getContext();
holder.fn = util.contextBind(context, holder.fn);
}
ret._setAsyncGuaranteed();
ret._setOnCancel(holder);
}
return ret;
}
}
}
INLINE_SLICE(args, arguments);
if (fn) args.pop();
var ret = new PromiseArray(args).promise();
return fn !== undefined ? ret.spread(fn) : ret;
};
};
================================================
FILE: src/map.js
================================================
"use strict";
module.exports = function(Promise,
PromiseArray,
apiRejection,
tryConvertToPromise,
INTERNAL,
debug) {
var ASSERT = require("./assert");
var util = require("./util");
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
var async = Promise._async;
function MappingPromiseArray(promises, fn, limit, _filter) {
this.constructor$(promises);
this._promise._captureStackTrace();
var context = Promise._getContext();
this._callback = util.contextBind(context, fn);
this._preservedValues = _filter === INTERNAL
? new Array(this.length())
: null;
this._limit = limit;
this._inFlight = 0;
this._queue = [];
async.invoke(this._asyncInit, this, undefined);
if (util.isArray(promises)) {
for (var i = 0; i < promises.length; ++i) {
var maybePromise = promises[i];
if (maybePromise instanceof Promise) {
maybePromise.suppressUnhandledRejections();
}
}
}
}
util.inherits(MappingPromiseArray, PromiseArray);
MappingPromiseArray.prototype._asyncInit = function() {
this._init$(undefined, RESOLVE_ARRAY);
};
// The following hack is required because the super constructor
// might call promiseFulfilled before this.callback = fn is set
//
// The super constructor call must always be first so that fields
// are initialized in the same order so that the sub-class instances
// will share same memory layout as the super class instances
// Override
MappingPromiseArray.prototype._init = function () {};
// Override
MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
ASSERT(!this._isResolved());
var values = this._values;
var length = this.length();
var preservedValues = this._preservedValues;
var limit = this._limit;
// Callback has been called for this index if it's negative
if (index < 0) {
// Restore the actual index value
index = (index * -1) - 1;
values[index] = value;
if (limit >= 1) {
this._inFlight--;
this._drainQueue();
if (this._isResolved()) return true;
}
} else {
if (limit >= 1 && this._inFlight >= limit) {
values[index] = value;
this._queue.push(index);
return false;
}
if (preservedValues !== null) preservedValues[index] = value;
var promise = this._promise;
var callback = this._callback;
var receiver = promise._boundValue();
promise._pushContext();
var ret = tryCatch(callback).call(receiver, value, index, length);
var promiseCreated = promise._popContext();
debug.checkForgottenReturns(
ret,
promiseCreated,
preservedValues !== null ? "Promise.filter" : "Promise.map",
promise
);
if (ret === errorObj) {
this._reject(ret.e);
return true;
}
// If the mapper function returned a promise we simply reuse
// The MappingPromiseArray as a PromiseArray for round 2.
// To mark an index as "round 2" its inverted by adding +1 and
// multiplying by -1
var maybePromise = tryConvertToPromise(ret, this._promise);
if (maybePromise instanceof Promise) {
maybePromise = maybePromise._target();
var bitField = maybePromise._bitField;
USE(bitField);
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
if (limit >= 1) this._inFlight++;
values[index] = maybePromise;
maybePromise._proxy(this, (index + 1) * -1);
return false;
} else if (BIT_FIELD_CHECK(IS_FULFILLED)) {
ret = maybePromise._value();
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
this._reject(maybePromise._reason());
return true;
} else {
this._cancel();
return true;
}
}
values[index] = ret;
}
var totalResolved = ++this._totalResolved;
if (totalResolved >= length) {
if (preservedValues !== null) {
this._filter(values, preservedValues);
} else {
this._resolve(values);
}
return true;
}
return false;
};
MappingPromiseArray.prototype._drainQueue = function () {
var queue = this._queue;
var limit = this._limit;
var values = this._values;
while (queue.length > 0 && this._inFlight < limit) {
if (this._isResolved()) return;
var index = queue.pop();
this._promiseFulfilled(values[index], index);
}
};
MappingPromiseArray.prototype._filter = function (booleans, values) {
var len = values.length;
var ret = new Array(len);
var j = 0;
for (var i = 0; i < len; ++i) {
if (booleans[i]) ret[j++] = values[i];
}
ret.length = j;
this._resolve(ret);
};
MappingPromiseArray.prototype.preservedValues = function () {
return this._preservedValues;
};
function map(promises, fn, options, _filter) {
if (typeof fn !== "function") {
return apiRejection(FUNCTION_ERROR + util.classString(fn));
}
var limit = 0;
if (options !== undefined) {
if (typeof options === "object" && options !== null) {
if (typeof options.concurrency !== "number") {
return Promise.reject(
new TypeError("'concurrency' must be a number but it is " +
util.classString(options.concurrency)));
}
limit = options.concurrency;
} else {
return Promise.reject(new TypeError(
"options argument must be an object but it is " +
util.classString(options)));
}
}
limit = typeof limit === "number" &&
isFinite(limit) && limit >= 1 ? limit : 0;
return new MappingPromiseArray(promises, fn, limit, _filter).promise();
}
Promise.prototype.map = function (fn, options) {
return map(this, fn, options, null);
};
Promise.map = function (promises, fn, options, _filter) {
return map(promises, fn, options, _filter);
};
};
================================================
FILE: src/method.js
================================================
"use strict";
module.exports =
function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) {
var util = require("./util");
var ASSERT = require("./assert");
var tryCatch = util.tryCatch;
Promise.method = function (fn) {
if (typeof fn !== "function") {
throw new Promise.TypeError(FUNCTION_ERROR + util.classString(fn));
}
return function () {
var ret = new Promise(INTERNAL);
ret._captureStackTrace();
ret._pushContext();
var value = tryCatch(fn).apply(this, arguments);
var promiseCreated = ret._popContext();
debug.checkForgottenReturns(
value, promiseCreated, "Promise.method", ret);
ret._resolveFromSyncValue(value);
return ret;
};
};
Promise.attempt = Promise["try"] = function (fn) {
if (typeof fn !== "function") {
return apiRejection(FUNCTION_ERROR + util.classString(fn));
}
var ret = new Promise(INTERNAL);
ret._captureStackTrace();
ret._pushContext();
var value;
if (arguments.length > 1) {
debug.deprecated("calling Promise.try with more than 1 argument");
var arg = arguments[1];
var ctx = arguments[2];
value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg)
: tryCatch(fn).call(ctx, arg);
} else {
value = tryCatch(fn)();
}
var promiseCreated = ret._popContext();
debug.checkForgottenReturns(
value, promiseCreated, "Promise.try", ret);
ret._resolveFromSyncValue(value);
return ret;
};
Promise.prototype._resolveFromSyncValue = function (value) {
ASSERT(!this._isFollowing());
if (value === util.errorObj) {
this._rejectCallback(value.e, false);
} else {
this._resolveCallback(value, true);
}
};
};
================================================
FILE: src/nodeback.js
================================================
"use strict";
var util = require("./util");
var maybeWrapAsError = util.maybeWrapAsError;
var errors = require("./errors");
var OperationalError = errors.OperationalError;
var es5 = require("./es5");
function isUntypedError(obj) {
return obj instanceof Error &&
es5.getPrototypeOf(obj) === Error.prototype;
}
var rErrorKey = /^(?:name|message|stack|cause)$/;
function wrapAsOperationalError(obj) {
var ret;
if (isUntypedError(obj)) {
ret = new OperationalError(obj);
ret.name = obj.name;
ret.message = obj.message;
ret.stack = obj.stack;
var keys = es5.keys(obj);
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
if (!rErrorKey.test(key)) {
ret[key] = obj[key];
}
}
return ret;
}
util.markAsOriginatingFromRejection(obj);
return obj;
}
function nodebackForPromise(promise, multiArgs) {
return function(err, value) {
if (promise === null) return;
if (err) {
var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
promise._attachExtraTrace(wrapped);
promise._reject(wrapped);
} else if (!multiArgs) {
promise._fulfill(value);
} else {
INLINE_SLICE(args, arguments, 1);
promise._fulfill(args);
}
promise = null;
};
}
module.exports = nodebackForPromise;
================================================
FILE: src/nodeify.js
================================================
"use strict";
module.exports = function(Promise) {
var util = require("./util");
var async = Promise._async;
var ASSERT = require("./assert");
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
function spreadAdapter(val, nodeback) {
var promise = this;
if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback);
var ret =
tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val));
if (ret === errorObj) {
async.throwLater(ret.e);
}
}
function successAdapter(val, nodeback) {
var promise = this;
var receiver = promise._boundValue();
ASSERT(typeof nodeback == "function");
var ret = val === undefined
? tryCatch(nodeback).call(receiver, null)
: tryCatch(nodeback).call(receiver, null, val);
if (ret === errorObj) {
async.throwLater(ret.e);
}
}
function errorAdapter(reason, nodeback) {
var promise = this;
if (!reason) {
var newReason = new Error(reason + "");
newReason.cause = reason;
reason = newReason;
ASSERT(!!reason);
}
ASSERT(typeof nodeback == "function");
var ret = tryCatch(nodeback).call(promise._boundValue(), reason);
if (ret === errorObj) {
async.throwLater(ret.e);
}
}
Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback,
options) {
if (typeof nodeback == "function") {
var adapter = successAdapter;
if (options !== undefined && Object(options).spread) {
adapter = spreadAdapter;
}
this._then(
adapter,
errorAdapter,
undefined,
this,
nodeback
);
}
return this;
};
};
================================================
FILE: src/promise.js
================================================
"use strict";
module.exports = function() {
var makeSelfResolutionError = function () {
return new TypeError(CIRCULAR_RESOLUTION_ERROR);
};
var reflectHandler = function() {
return new Promise.PromiseInspection(this._target());
};
var apiRejection = function(msg) {
return Promise.reject(new TypeError(msg));
};
function Proxyable() {}
var UNDEFINED_BINDING = {};
var ASSERT = require("./assert");
var util = require("./util");
util.setReflectHandler(reflectHandler);
var getDomain = function() {
var domain = process.domain;
if (domain === undefined) {
return null;
}
return domain;
};
var getContextDefault = function() {
return null;
};
var getContextDomain = function() {
return {
domain: getDomain(),
async: null
};
};
var AsyncResource = util.isNode && util.nodeSupportsAsyncResource ?
require("async_hooks").AsyncResource : null;
var getContextAsyncHooks = function() {
return {
domain: getDomain(),
async: new AsyncResource("Bluebird::Promise")
};
};
var getContext = util.isNode ? getContextDomain : getContextDefault;
util.notEnumerableProp(Promise, "_getContext", getContext);
var enableAsyncHooks = function() {
getContext = getContextAsyncHooks;
util.notEnumerableProp(Promise, "_getContext", getContextAsyncHooks);
};
var disableAsyncHooks = function() {
getContext = getContextDomain;
util.notEnumerableProp(Promise, "_getContext", getContextDomain);
};
var es5 = require("./es5");
var Async = require("./async");
var async = new Async();
es5.defineProperty(Promise, "_async", {value: async});
var errors = require("./errors");
var TypeError = Promise.TypeError = errors.TypeError;
Promise.RangeError = errors.RangeError;
var CancellationError = Promise.CancellationError = errors.CancellationError;
Promise.TimeoutError = errors.TimeoutError;
Promise.OperationalError = errors.OperationalError;
Promise.RejectionError = errors.OperationalError;
Promise.AggregateError = errors.AggregateError;
var INTERNAL = function(){};
var APPLY = {};
var NEXT_FILTER = {};
var tryConvertToPromise = require("./thenables")(Promise, INTERNAL);
var PromiseArray =
require("./promise_array")(Promise, INTERNAL,
tryConvertToPromise, apiRejection, Proxyable);
var Context = require("./context")(Promise);
/*jshint unused:false*/
var createContext = Context.create;
var debug = require("./debuggability")(Promise, Context,
enableAsyncHooks, disableAsyncHooks);
var CapturedTrace = debug.CapturedTrace;
var PassThroughHandlerContext =
require("./finally")(Promise, tryConvertToPromise, NEXT_FILTER);
var catchFilter = require("./catch_filter")(NEXT_FILTER);
var nodebackForPromise = require("./nodeback");
var errorObj = util.errorObj;
var tryCatch = util.tryCatch;
function check(self, executor) {
if (self == null || self.constructor !== Promise) {
throw new TypeError(CONSTRUCT_ERROR_INVOCATION);
}
if (typeof executor !== "function") {
throw new TypeError(FUNCTION_ERROR + util.classString(executor));
}
}
function Promise(executor) {
if (executor !== INTERNAL) {
check(this, executor);
}
this._bitField = NO_STATE;
this._fulfillmentHandler0 = undefined;
this._rejectionHandler0 = undefined;
this._promise0 = undefined;
this._receiver0 = undefined;
this._resolveFromExecutor(executor);
this._promiseCreated();
this._fireEvent("promiseCreated", this);
}
Promise.prototype.toString = function () {
return "[object Promise]";
};
Promise.prototype.caught = Promise.prototype["catch"] = function (fn) {
var len = arguments.length;
if (len > 1) {
var catchInstances = new Array(len - 1),
j = 0, i;
for (i = 0; i < len - 1; ++i) {
var item = arguments[i];
if (util.isObject(item)) {
catchInstances[j++] = item;
} else {
return apiRejection("Catch statement predicate: " +
OBJECT_ERROR + util.classString(item));
}
}
catchInstances.length = j;
fn = arguments[i];
if (typeof fn !== "function") {
throw new TypeError("The last argument to .catch() " +
"must be a function, got " + util.toString(fn));
}
return this.then(undefined, catchFilter(catchInstances, fn, this));
}
return this.then(undefined, fn);
};
Promise.prototype.reflect = function () {
return this._then(reflectHandler,
reflectHandler, undefined, this, undefined);
};
Promise.prototype.then = function (didFulfill, didReject) {
if (debug.warnings() && arguments.length > 0 &&
typeof didFulfill !== "function" &&
typeof didReject !== "function") {
var msg = ".then() only accepts functions but was passed: " +
util.classString(didFulfill);
if (arguments.length > 1) {
msg += ", " + util.classString(didReject);
}
this._warn(msg);
}
return this._then(didFulfill, didReject, undefined, undefined, undefined);
};
Promise.prototype.done = function (didFulfill, didReject) {
var promise =
this._then(didFulfill, didReject, undefined, undefined, undefined);
promise._setIsFinal();
};
Promise.prototype.spread = function (fn) {
if (typeof fn !== "function") {
return apiRejection(FUNCTION_ERROR + util.classString(fn));
}
return this.all()._then(fn, undefined, undefined, APPLY, undefined);
};
Promise.prototype.toJSON = function () {
var ret = {
isFulfilled: false,
isRejected: false,
fulfillmentValue: undefined,
rejectionReason: undefined
};
if (this.isFulfilled()) {
ret.fulfillmentValue = this.value();
ret.isFulfilled = true;
} else if (this.isRejected()) {
ret.rejectionReason = this.reason();
ret.isRejected = true;
}
return ret;
};
Promise.prototype.all = function () {
if (arguments.length > 0) {
this._warn(".all() was passed arguments but it does not take any");
}
return new PromiseArray(this).promise();
};
Promise.prototype.error = function (fn) {
return this.caught(util.originatesFromRejection, fn);
};
Promise.getNewLibraryCopy = module.exports;
Promise.is = function (val) {
return val instanceof Promise;
};
Promise.fromNode = Promise.fromCallback = function(fn) {
var ret = new Promise(INTERNAL);
ret._captureStackTrace();
var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs
: false;
var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs));
if (result === errorObj) {
ret._rejectCallback(result.e, true);
}
if (!ret._isFateSealed()) ret._setAsyncGuaranteed();
return ret;
};
Promise.all = function (promises) {
return new PromiseArray(promises).promise();
};
Promise.cast = function (obj) {
var ret = tryConvertToPromise(obj);
if (!(ret instanceof Promise)) {
ret = new Promise(INTERNAL);
ret._captureStackTrace();
ret._setFulfilled();
ret._rejectionHandler0 = obj;
}
return ret;
};
Promise.resolve = Promise.fulfilled = Promise.cast;
Promise.reject = Promise.rejected = function (reason) {
var ret = new Promise(INTERNAL);
ret._captureStackTrace();
ret._rejectCallback(reason, true);
return ret;
};
Promise.setScheduler = function(fn) {
if (typeof fn !== "function") {
throw new TypeError(FUNCTION_ERROR + util.classString(fn));
}
return async.setScheduler(fn);
};
Promise.prototype._then = function (
didFulfill,
didReject,
_, // For fast-cast compatibility between bluebird versions
receiver,
internalData
) {
ASSERT(arguments.length === 5);
var haveInternalData = internalData !== undefined;
var promise = haveInternalData ? internalData : new Promise(INTERNAL);
var target = this._target();
var bitField = target._bitField;
if (!haveInternalData) {
promise._propagateFrom(this, PROPAGATE_ALL);
promise._captureStackTrace();
if (receiver === undefined &&
BIT_FIELD_CHECK(IS_BOUND, this._bitField)) {
if (!BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
receiver = this._boundValue();
} else {
receiver = target === this ? undefined : this._boundTo;
}
}
this._fireEvent("promiseChained", this, promise);
}
var context = getContext();
if (!BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
var handler, value, settler = target._settlePromiseCtx;
if (BIT_FIELD_CHECK(IS_FULFILLED)) {
value = target._rejectionHandler0;
handler = didFulfill;
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
value = target._fulfillmentHandler0;
handler = didReject;
target._unsetRejectionIsUnhandled();
} else {
settler = target._settlePromiseLateCancellationObserver;
value = new CancellationError(LATE_CANCELLATION_OBSERVER);
target._attachExtraTrace(value);
handler = didReject;
}
async.invoke(settler, target, {
handler: util.contextBind(context, handler),
promise: promise,
receiver: receiver,
value: value
});
} else {
target._addCallbacks(didFulfill, didReject, promise,
receiver, context);
}
return promise;
};
Promise.prototype._length = function () {
ASSERT(arguments.length === 0);
return this._bitField & LENGTH_MASK;
};
Promise.prototype._isFateSealed = function () {
return (this._bitField & IS_FATE_SEALED) !== 0;
};
Promise.prototype._isFollowing = function () {
return (this._bitField & IS_FOLLOWING) === IS_FOLLOWING;
};
Promise.prototype._setLength = function (len) {
this._bitField = (this._bitField & LENGTH_CLEAR_MASK) |
(len & LENGTH_MASK);
};
Promise.prototype._setFulfilled = function () {
this._bitField = this._bitField | IS_FULFILLED;
this._fireEvent("promiseFulfilled", this);
};
Promise.prototype._setRejected = function () {
this._bitField = this._bitField | IS_REJECTED;
this._fireEvent("promiseRejected", this);
};
Promise.prototype._setFollowing = function () {
this._bitField = this._bitField | IS_FOLLOWING;
this._fireEvent("promiseResolved", this);
};
Promise.prototype._setIsFinal = function () {
this._bitField = this._bitField | IS_FINAL;
};
Promise.prototype._isFinal = function () {
return (this._bitField & IS_FINAL) > 0;
};
Promise.prototype._unsetCancelled = function() {
this._bitField = this._bitField & (~IS_CANCELLED);
};
Promise.prototype._setCancelled = function() {
this._bitField = this._bitField | IS_CANCELLED;
this._fireEvent("promiseCancelled", this);
};
Promise.prototype._setWillBeCancelled = function() {
this._bitField = this._bitField | WILL_BE_CANCELLED;
};
Promise.prototype._setAsyncGuaranteed = function() {
if (async.hasCustomScheduler()) return;
var bitField = this._bitField;
this._bitField = bitField |
(((bitField & NO_ASYNC_GUARANTEE) >> ASYNC_GUARANTEE_SHIFT) ^
IS_ASYNC_GUARANTEED);
};
Promise.prototype._setNoAsyncGuarantee = function() {
this._bitField = (this._bitField | NO_ASYNC_GUARANTEE) &
(~IS_ASYNC_GUARANTEED);
};
Promise.prototype._receiverAt = function (index) {
ASSERT(!this._isFollowing());
var ret = index === 0 ? this._receiver0 : this[
index * CALLBACK_SIZE - CALLBACK_SIZE + CALLBACK_RECEIVER_OFFSET];
//Only use the bound value when not calling internal methods
if (ret === UNDEFINED_BINDING) {
return undefined;
} else if (ret === undefined && this._isBound()) {
return this._boundValue();
}
return ret;
};
Promise.prototype._promiseAt = function (index) {
ASSERT(index > 0);
ASSERT(!this._isFollowing());
return this[
index * CALLBACK_SIZE - CALLBACK_SIZE + CALLBACK_PROMISE_OFFSET];
};
Promise.prototype._fulfillmentHandlerAt = function (index) {
ASSERT(!this._isFollowing());
ASSERT(index > 0);
return this[
index * CALLBACK_SIZE - CALLBACK_SIZE + CALLBACK_FULFILL_OFFSET];
};
Promise.prototype._rejectionHandlerAt = function (index) {
ASSERT(!this._isFollowing());
ASSERT(index > 0);
return this[
index * CALLBACK_SIZE - CALLBACK_SIZE + CALLBACK_REJECT_OFFSET];
};
Promise.prototype._boundValue = function() {};
Promise.prototype._migrateCallback0 = function (follower) {
var bitField = follower._bitField;
var fulfill = follower._fulfillmentHandler0;
var reject = follower._rejectionHandler0;
var promise = follower._promise0;
var receiver = follower._receiverAt(0);
if (receiver === undefined) receiver = UNDEFINED_BINDING;
this._addCallbacks(fulfill, reject, promise, receiver, null);
};
Promise.prototype._migrateCallbackAt = function (follower, index) {
ASSERT(index > 0);
var fulfill = follower._fulfillmentHandlerAt(index);
var reject = follower._rejectionHandlerAt(index);
var promise = follower._promiseAt(index);
var receiver = follower._receiverAt(index);
if (receiver === undefined) receiver = UNDEFINED_BINDING;
this._addCallbacks(fulfill, reject, promise, receiver, null);
};
Promise.prototype._addCallbacks = function (
fulfill,
reject,
promise,
receiver,
context
) {
ASSERT(typeof context === "object");
ASSERT(!this._isFateSealed());
ASSERT(!this._isFollowing());
var index = this._length();
if (index >= MAX_LENGTH - CALLBACK_SIZE) {
index = 0;
this._setLength(0);
}
if (index === 0) {
ASSERT(this._promise0 === undefined);
ASSERT(this._receiver0 === undefined);
ASSERT(this._fulfillmentHandler0 === undefined);
ASSERT(this._rejectionHandler0 === undefined);
this._promise0 = promise;
this._receiver0 = receiver;
if (typeof fulfill === "function") {
this._fulfillmentHandler0 = util.contextBind(context, fulfill);
}
if (typeof reject === "function") {
this._rejectionHandler0 = util.contextBind(context, reject);
}
} else {
ASSERT(this[base + CALLBACK_PROMISE_OFFSET] === undefined);
ASSERT(this[base + CALLBACK_RECEIVER_OFFSET] === undefined);
ASSERT(this[base + CALLBACK_FULFILL_OFFSET] === undefined);
ASSERT(this[base + CALLBACK_REJECT_OFFSET] === undefined);
var base = index * CALLBACK_SIZE - CALLBACK_SIZE;
this[base + CALLBACK_PROMISE_OFFSET] = promise;
this[base + CALLBACK_RECEIVER_OFFSET] = receiver;
if (typeof fulfill === "function") {
this[base + CALLBACK_FULFILL_OFFSET] =
util.contextBind(context, fulfill);
}
if (typeof reject === "function") {
this[base + CALLBACK_REJECT_OFFSET] =
util.contextBind(context, reject);
}
}
this._setLength(index + 1);
return index;
};
Promise.prototype._proxy = function (proxyable, arg) {
ASSERT(proxyable instanceof Proxyable);
ASSERT(!(arg instanceof Promise));
ASSERT(!this._isFollowing());
ASSERT(arguments.length === 2);
ASSERT(!this._isFateSealed());
this._addCallbacks(undefined, undefined, arg, proxyable, null);
};
Promise.prototype._resolveCallback = function(value, shouldBind) {
if (BIT_FIELD_CHECK(IS_FATE_SEALED, this._bitField)) return;
if (value === this)
return this._rejectCallback(makeSelfResolutionError(), false);
var maybePromise = tryConvertToPromise(value, this);
if (!(maybePromise instanceof Promise)) return this._fulfill(value);
if (shouldBind) this._propagateFrom(maybePromise, PROPAGATE_BIND);
var promise = maybePromise._target();
if (promise === this) {
this._reject(makeSelfResolutionError());
return;
}
var bitField = promise._bitField;
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
var len = this._length();
if (len > 0) promise._migrateCallback0(this);
for (var i = 1; i < len; ++i) {
promise._migrateCallbackAt(this, i);
}
this._setFollowing();
this._setLength(0);
this._setFollowee(maybePromise);
} else if (BIT_FIELD_CHECK(IS_FULFILLED)) {
this._fulfill(promise._value());
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
this._reject(promise._reason());
} else {
var reason = new CancellationError(LATE_CANCELLATION_OBSERVER);
promise._attachExtraTrace(reason);
this._reject(reason);
}
};
Promise.prototype._rejectCallback =
function(reason, synchronous, ignoreNonErrorWarnings) {
var trace = util.ensureErrorObject(reason);
var hasStack = trace === reason;
if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) {
var message = "a promise was rejected with a non-error: " +
util.classString(reason);
this._warn(message, true);
}
this._attachExtraTrace(trace, synchronous ? hasStack : false);
this._reject(reason);
};
Promise.prototype._resolveFromExecutor = function (executor) {
if (executor === INTERNAL) return;
ASSERT(typeof executor === "function");
var promise = this;
this._captureStackTrace();
this._pushContext();
var synchronous = true;
var r = this._execute(executor, function(value) {
promise._resolveCallback(value);
}, function (reason) {
promise._rejectCallback(reason, synchronous);
});
synchronous = false;
this._popContext();
if (r !== undefined) {
promise._rejectCallback(r, true);
}
};
Promise.prototype._settlePromiseFromHandler = function (
handler, receiver, value, promise
) {
var bitField = promise._bitField;
if (BIT_FIELD_CHECK(IS_CANCELLED)) return;
promise._pushContext();
var x;
if (receiver === APPLY) {
if (!value || typeof value.length !== "number") {
x = errorObj;
x.e = new TypeError("cannot .spread() a non-array: " +
util.classString(value));
} else {
x = tryCatch(handler).apply(this._boundValue(), value);
}
} else {
x = tryCatch(handler).call(receiver, value);
}
var promiseCreated = promise._popContext();
bitField = promise._bitField;
if (BIT_FIELD_CHECK(IS_CANCELLED)) return;
ASSERT(!promise._isFateSealed());
if (x === NEXT_FILTER) {
promise._reject(value);
} else if (x === errorObj) {
promise._rejectCallback(x.e, false);
} else {
debug.checkForgottenReturns(x, promiseCreated, "", promise, this);
promise._resolveCallback(x);
}
};
Promise.prototype._target = function() {
var ret = this;
while (ret._isFollowing()) ret = ret._followee();
return ret;
};
Promise.prototype._followee = function() {
ASSERT(this._isFollowing());
ASSERT(this._rejectionHandler0 instanceof Promise);
return this._rejectionHandler0;
};
Promise.prototype._setFollowee = function(promise) {
ASSERT(this._isFollowing());
ASSERT(!(this._rejectionHandler0 instanceof Promise));
this._rejectionHandler0 = promise;
};
Promise.prototype._settlePromise = function(promise, handler, receiver, value) {
ASSERT(!this._isFollowing());
var isPromise = promise instanceof Promise;
var bitField = this._bitField;
var asyncGuaranteed = BIT_FIELD_CHECK(IS_ASYNC_GUARANTEED);
if (BIT_FIELD_CHECK(IS_CANCELLED)) {
if (isPromise) promise._invokeInternalOnCancel();
if (receiver instanceof PassThroughHandlerContext &&
receiver.isFinallyHandler()) {
receiver.cancelPromise = promise;
if (tryCatch(handler).call(receiver, value) === errorObj) {
promise._reject(errorObj.e);
}
} else if (handler === reflectHandler) {
promise._fulfill(reflectHandler.call(receiver));
} else if (receiver instanceof Proxyable) {
receiver._promiseCancelled(promise);
} else if (isPromise || promise instanceof PromiseArray) {
promise._cancel();
} else {
receiver.cancel();
}
} else if (typeof handler === "function") {
//if promise is not instanceof Promise
//it is internally smuggled data
if (!isPromise) {
handler.call(receiver, value, promise);
} else {
if (asyncGuaranteed) promise._setAsyncGuaranteed();
this._settlePromiseFromHandler(handler, receiver, value, promise);
}
} else if (receiver instanceof Proxyable) {
if (!receiver._isResolved()) {
if (BIT_FIELD_CHECK(IS_FULFILLED)) {
receiver._promiseFulfilled(value, promise);
} else {
receiver._promiseRejected(value, promise);
}
}
} else if (isPromise) {
if (asyncGuaranteed) promise._setAsyncGuaranteed();
if (BIT_FIELD_CHECK(IS_FULFILLED)) {
promise._fulfill(value);
} else {
promise._reject(value);
}
}
};
Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) {
var handler = ctx.handler;
var promise = ctx.promise;
var receiver = ctx.receiver;
var value = ctx.value;
if (typeof handler === "function") {
if (!(promise instanceof Promise)) {
handler.call(receiver, value, promise);
} else {
this._settlePromiseFromHandler(handler, receiver, value, promise);
}
} else if (promise instanceof Promise) {
promise._reject(value);
}
};
Promise.prototype._settlePromiseCtx = function(ctx) {
this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value);
};
Promise.prototype._settlePromise0 = function(handler, value, bitField) {
var promise = this._promise0;
var receiver = this._receiverAt(0);
this._promise0 = undefined;
this._receiver0 = undefined;
this._settlePromise(promise, handler, receiver, value);
};
Promise.prototype._clearCallbackDataAtIndex = function(index) {
ASSERT(!this._isFollowing());
ASSERT(index > 0);
var base = index * CALLBACK_SIZE - CALLBACK_SIZE;
this[base + CALLBACK_PROMISE_OFFSET] =
this[base + CALLBACK_RECEIVER_OFFSET] =
this[base + CALLBACK_FULFILL_OFFSET] =
this[base + CALLBACK_REJECT_OFFSET] = undefined;
};
Promise.prototype._fulfill = function (value) {
var bitField = this._bitField;
if (BIT_FIELD_READ(IS_FATE_SEALED)) return;
if (value === this) {
var err = makeSelfResolutionError();
this._attachExtraTrace(err);
return this._reject(err);
}
this._setFulfilled();
this._rejectionHandler0 = value;
if (BIT_FIELD_READ(LENGTH_MASK) > 0) {
if (BIT_FIELD_CHECK(IS_ASYNC_GUARANTEED)) {
this._settlePromises();
} else {
async.settlePromises(this);
}
this._dereferenceTrace();
}
};
Promise.prototype._reject = function (reason) {
var bitField = this._bitField;
if (BIT_FIELD_READ(IS_FATE_SEALED)) return;
this._setRejected();
this._fulfillmentHandler0 = reason;
if (this._isFinal()) {
ASSERT(this._length() === 0);
return async.fatalError(reason, util.isNode);
}
if (BIT_FIELD_READ(LENGTH_MASK) > 0) {
async.settlePromises(this);
} else {
this._ensurePossibleRejectionHandled();
}
};
Promise.prototype._fulfillPromises = function (len, value) {
for (var i = 1; i < len; i++) {
var handler = this._fulfillmentHandlerAt(i);
var promise = this._promiseAt(i);
var receiver = this._receiverAt(i);
this._clearCallbackDataAtIndex(i);
this._settlePromise(promise, handler, receiver, value);
}
};
Promise.prototype._rejectPromises = function (len, reason) {
for (var i = 1; i < len; i++) {
var handler = this._rejectionHandlerAt(i);
var promise = this._promiseAt(i);
var receiver = this._receiverAt(i);
this._clearCallbackDataAtIndex(i);
this._settlePromise(promise, handler, receiver, reason);
}
};
Promise.prototype._settlePromises = function () {
var bitField = this._bitField;
var len = BIT_FIELD_READ(LENGTH_MASK);
if (len > 0) {
if (BIT_FIELD_CHECK(IS_REJECTED_OR_CANCELLED)) {
var reason = this._fulfillmentHandler0;
this._settlePromise0(this._rejectionHandler0, reason, bitField);
this._rejectPromises(len, reason);
} else {
var value = this._rejectionHandler0;
this._settlePromise0(this._fulfillmentHandler0, value, bitField);
this._fulfillPromises(len, value);
}
this._setLength(0);
}
this._clearCancellationData();
};
Promise.prototype._settledValue = function() {
ASSERT(!this._isFollowing());
ASSERT(this._isFateSealed());
var bitField = this._bitField;
if (BIT_FIELD_CHECK(IS_FULFILLED)) {
return this._rejectionHandler0;
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
return this._fulfillmentHandler0;
}
// Implicit undefined for cancelled promise.
};
if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
es5.defineProperty(Promise.prototype, Symbol.toStringTag, {
get: function () {
return "Object";
}
});
}
function deferResolve(v) {this.promise._resolveCallback(v);}
function deferReject(v) {this.promise._rejectCallback(v, false);}
Promise.defer = Promise.pending = function() {
debug.deprecated("Promise.defer", "new Promise");
var promise = new Promise(INTERNAL);
return {
promise: promise,
resolve: deferResolve,
reject: deferReject
};
};
util.notEnumerableProp(Promise,
"_makeSelfResolutionError",
makeSelfResolutionError);
require("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection,
debug);
require("./bind")(Promise, INTERNAL, tryConvertToPromise, debug);
require("./cancel")(Promise, PromiseArray, apiRejection, debug);
require("./direct_resolve")(Promise);
require("./synchronous_inspection")(Promise);
require("./join")(
Promise, PromiseArray, tryConvertToPromise, INTERNAL, async);
Promise.Promise = Promise;
Promise.version = "__VERSION__";
};
================================================
FILE: src/promise_array.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL, tryConvertToPromise,
apiRejection, Proxyable) {
var ASSERT = require("./assert");
var util = require("./util");
var isArray = util.isArray;
//To avoid eagerly allocating the objects
//and also because undefined cannot be smuggled
function toResolutionValue(val) {
switch(val) {
case RESOLVE_ARRAY: return [];
case RESOLVE_OBJECT: return {};
case RESOLVE_MAP: return new Map();
}
ASSERT(false);
}
function PromiseArray(values) {
ASSERT(arguments.length === 1);
var promise = this._promise = new Promise(INTERNAL);
if (values instanceof Promise) {
promise._propagateFrom(values, PROPAGATE_ALL);
values.suppressUnhandledRejections();
}
promise._setOnCancel(this);
this._values = values;
this._length = 0;
this._totalResolved = 0;
this._init(undefined, RESOLVE_ARRAY);
}
util.inherits(PromiseArray, Proxyable);
PromiseArray.prototype.length = function () {
return this._length;
};
PromiseArray.prototype.promise = function () {
return this._promise;
};
PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) {
var values = tryConvertToPromise(this._values, this._promise);
if (values instanceof Promise) {
values = values._target();
var bitField = values._bitField;
USE(bitField);
this._values = values;
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
ASSERT(typeof resolveValueIfEmpty === "number");
ASSERT(resolveValueIfEmpty < 0);
this._promise._setAsyncGuaranteed();
return values._then(
init,
this._reject,
undefined,
this,
resolveValueIfEmpty
);
} else if (BIT_FIELD_CHECK(IS_FULFILLED)) {
values = values._value();
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
return this._reject(values._reason());
} else {
return this._cancel();
}
}
values = util.asArray(values);
if (values === null) {
var err = apiRejection(
COLLECTION_ERROR + util.classString(values)).reason();
this._promise._rejectCallback(err, false);
return;
}
if (values.length === 0) {
if (resolveValueIfEmpty === RESOLVE_CALL_METHOD) {
this._resolveEmptyArray();
}
else {
this._resolve(toResolutionValue(resolveValueIfEmpty));
}
return;
}
this._iterate(values);
};
PromiseArray.prototype._iterate = function(values) {
var len = this.getActualLength(values.length);
this._length = len;
this._values = this.shouldCopyValues() ? new Array(len) : this._values;
var result = this._promise;
var isResolved = false;
var bitField = null;
for (var i = 0; i < len; ++i) {
var maybePromise = tryConvertToPromise(values[i], result);
if (maybePromise instanceof Promise) {
maybePromise = maybePromise._target();
bitField = maybePromise._bitField;
} else {
bitField = null;
}
if (isResolved) {
if (bitField !== null) {
maybePromise.suppressUnhandledRejections();
}
} else if (bitField !== null) {
if (BIT_FIELD_CHECK(IS_PENDING_AND_WAITING_NEG)) {
// Optimized for just passing the updates through
maybePromise._proxy(this, i);
this._values[i] = maybePromise;
} else if (BIT_FIELD_CHECK(IS_FULFILLED)) {
isResolved = this._promiseFulfilled(maybePromise._value(), i);
} else if (BIT_FIELD_CHECK(IS_REJECTED)) {
isResolved = this._promiseRejected(maybePromise._reason(), i);
} else {
isResolved = this._promiseCancelled(i);
}
} else {
isResolved = this._promiseFulfilled(maybePromise, i);
}
ASSERT(typeof isResolved === "boolean");
}
if (!isResolved) result._setAsyncGuaranteed();
};
PromiseArray.prototype._isResolved = function () {
return this._values === null;
};
PromiseArray.prototype._resolve = function (value) {
ASSERT(!this._isResolved());
ASSERT(!(value instanceof Promise));
this._values = null;
this._promise._fulfill(value);
};
PromiseArray.prototype._cancel = function() {
if (this._isResolved() || !this._promise._isCancellable()) return;
this._values = null;
this._promise._cancel();
};
PromiseArray.prototype._reject = function (reason) {
ASSERT(!this._isResolved());
this._values = null;
this._promise._rejectCallback(reason, false);
};
PromiseArray.prototype._promiseFulfilled = function (value, index) {
ASSERT(!this._isResolved());
ASSERT(isArray(this._values));
ASSERT(typeof index === "number");
this._values[index] = value;
var totalResolved = ++this._totalResolved;
if (totalResolved >= this._length) {
this._resolve(this._values);
return true;
}
return false;
};
PromiseArray.prototype._promiseCancelled = function() {
this._cancel();
return true;
};
PromiseArray.prototype._promiseRejected = function (reason) {
ASSERT(!this._isResolved());
ASSERT(isArray(this._values));
this._totalResolved++;
this._reject(reason);
return true;
};
PromiseArray.prototype._resultCancelled = function() {
if (this._isResolved()) return;
var values = this._values;
this._cancel();
if (values instanceof Promise) {
values.cancel();
} else {
for (var i = 0; i < values.length; ++i) {
if (values[i] instanceof Promise) {
values[i].cancel();
}
}
}
};
PromiseArray.prototype.shouldCopyValues = function () {
return true;
};
PromiseArray.prototype.getActualLength = function (len) {
return len;
};
return PromiseArray;
};
================================================
FILE: src/promisify.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL) {
var THIS = {};
var util = require("./util");
var nodebackForPromise = require("./nodeback");
var withAppended = util.withAppended;
var maybeWrapAsError = util.maybeWrapAsError;
var canEvaluate = util.canEvaluate;
var ASSERT = require("./assert");
var TypeError = require("./errors").TypeError;
var defaultSuffix = AFTER_PROMISIFIED_SUFFIX;
var defaultPromisified = {__isPromisified__: true};
var noCopyProps = [
"arity", // Firefox 4
"length",
"name",
"arguments",
"caller",
"callee",
"prototype",
"__isPromisified__"
];
var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$");
var defaultFilter = function(name) {
return util.isIdentifier(name) &&
name.charAt(0) !== "_" &&
name !== "constructor";
};
function propsFilter(key) {
return !noCopyPropsPattern.test(key);
}
function isPromisified(fn) {
try {
return fn.__isPromisified__ === true;
}
catch (e) {
return false;
}
}
function hasPromisified(obj, key, suffix) {
var val = util.getDataPropertyOrDefault(obj, key + suffix,
defaultPromisified);
return val ? isPromisified(val) : false;
}
function checkValid(ret, suffix, suffixRegexp) {
// Verify that in the list of methods to promisify there is no
// method that has a name ending in "Async"-suffix while
// also having a method with the same name but no Async suffix
for (var i = 0; i < ret.length; i += 2) {
var key = ret[i];
if (suffixRegexp.test(key)) {
var keyWithoutAsyncSuffix = key.replace(suffixRegexp, "");
for (var j = 0; j < ret.length; j += 2) {
if (ret[j] === keyWithoutAsyncSuffix) {
throw new TypeError(PROMISIFICATION_NORMAL_METHODS_ERROR
.replace("%s", suffix));
}
}
}
}
}
function promisifiableMethods(obj, suffix, suffixRegexp, filter) {
var keys = util.inheritedDataKeys(obj);
var ret = [];
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
var value = obj[key];
var passesDefaultFilter = filter === defaultFilter
? true : defaultFilter(key, value, obj);
if (typeof value === "function" &&
!isPromisified(value) &&
!hasPromisified(obj, key, suffix) &&
filter(key, value, obj, passesDefaultFilter)) {
ret.push(key, value);
}
}
checkValid(ret, suffix, suffixRegexp);
return ret;
}
var escapeIdentRegex = function(str) {
return str.replace(/([$])/, "\\$");
};
var makeNodePromisifiedEval;
if (!__BROWSER__) {
//Gives an optimal sequence of argument count to try given a formal parameter
//.length for a function
var switchCaseArgumentOrder = function(likelyArgumentCount) {
var ret = [likelyArgumentCount];
var min = Math.max(0, likelyArgumentCount - 1 - PARAM_COUNTS_TO_TRY);
for(var i = likelyArgumentCount - 1; i >= min; --i) {
ret.push(i);
}
for(var i = likelyArgumentCount + 1; i <= PARAM_COUNTS_TO_TRY; ++i) {
ret.push(i);
}
return ret;
};
var argumentSequence = function(argumentCount) {
return util.filledRange(argumentCount, "_arg", "");
};
var parameterDeclaration = function(parameterCount) {
return util.filledRange(
Math.max(parameterCount, PARAM_COUNTS_TO_TRY), "_arg", "");
};
var parameterCount = function(fn) {
if (typeof fn.length === "number") {
return Math.max(Math.min(fn.length, MAX_PARAM_COUNT + 1), 0);
}
//Unsupported .length for functions
return 0;
};
makeNodePromisifiedEval =
function(callback, receiver, originalName, fn, _, multiArgs) {
//-1 for the callback parameter
var newParameterCount = Math.max(0, parameterCount(fn) - 1);
var argumentOrder = switchCaseArgumentOrder(newParameterCount);
var shouldProxyThis = typeof callback === "string" || receiver === THIS;
function generateCallForArgumentCount(count) {
var args = argumentSequence(count).join(", ");
var comma = count > 0 ? ", " : "";
var ret;
if (shouldProxyThis) {
ret = "ret = callback.call(this, {{args}}, nodeback); break;\n";
} else {
ret = receiver === undefined
? "ret = callback({{args}}, nodeback); break;\n"
: "ret = callback.call(receiver, {{args}}, nodeback); break;\n";
}
return ret.replace("{{args}}", args).replace(", ", comma);
}
function generateArgumentSwitchCase() {
var ret = "";
for (var i = 0; i < argumentOrder.length; ++i) {
ret += "case " + argumentOrder[i] +":" +
generateCallForArgumentCount(argumentOrder[i]);
}
ret += " \n\
default: \n\
var args = new Array(len + 1); \n\
var i = 0; \n\
for (var i = 0; i < len; ++i) { \n\
args[i] = arguments[i]; \n\
} \n\
args[i] = nodeback; \n\
[CodeForCall] \n\
break; \n\
".replace("[CodeForCall]", (shouldProxyThis
? "ret = callback.apply(this, args);\n"
: "ret = callback.apply(receiver, args);\n"));
return ret;
}
var getFunctionCode = typeof callback === "string"
? ("this != null ? this['"+callback+"'] : fn")
: "fn";
var body = "'use strict'; \n\
var ret = function (Parameters) { \n\
'use strict'; \n\
var len = arguments.length; \n\
var promise = new Promise(INTERNAL); \n\
promise._captureStackTrace(); \n\
var nodeback = nodebackForPromise(promise, " + multiArgs + "); \n\
var ret; \n\
var callback = tryCatch([GetFunctionCode]); \n\
switch(len) { \n\
[CodeForSwitchCase] \n\
} \n\
if (ret === errorObj) { \n\
promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\
} \n\
if (!promise._isFateSealed()) promise._setAsyncGuaranteed(); \n\
return promise; \n\
}; \n\
notEnumerableProp(ret, '__isPromisified__', true); \n\
return ret; \n\
".replace("[CodeForSwitchCase]", generateArgumentSwitchCase())
.replace("[GetFunctionCode]", getFunctionCode);
body = body.replace("Parameters", parameterDeclaration(newParameterCount));
return new Function("Promise",
"fn",
"receiver",
"withAppended",
"maybeWrapAsError",
"nodebackForPromise",
"tryCatch",
"errorObj",
"notEnumerableProp",
"INTERNAL",
body)(
Promise,
fn,
receiver,
withAppended,
maybeWrapAsError,
nodebackForPromise,
util.tryCatch,
util.errorObj,
util.notEnumerableProp,
INTERNAL);
};
}
function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) {
var defaultThis = (function() {return this;})();
var method = callback;
if (typeof method === "string") {
callback = fn;
}
function promisified() {
var _receiver = receiver;
if (receiver === THIS) _receiver = this;
ASSERT(typeof callback === "function");
var promise = new Promise(INTERNAL);
promise._captureStackTrace();
var cb = typeof method === "string" && this !== defaultThis
? this[method] : callback;
var fn = nodebackForPromise(promise, multiArgs);
try {
cb.apply(_receiver, withAppended(arguments, fn));
} catch(e) {
promise._rejectCallback(maybeWrapAsError(e), true, true);
}
if (!promise._isFateSealed()) promise._setAsyncGuaranteed();
return promise;
}
util.notEnumerableProp(promisified, "__isPromisified__", true);
return promisified;
}
var makeNodePromisified = canEvaluate
? makeNodePromisifiedEval
: makeNodePromisifiedClosure;
function promisifyAll(obj, suffix, filter, promisifier, multiArgs) {
ASSERT(typeof suffix === "string");
ASSERT(typeof filter === "function");
var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$");
var methods =
promisifiableMethods(obj, suffix, suffixRegexp, filter);
for (var i = 0, len = methods.length; i < len; i+= 2) {
var key = methods[i];
var fn = methods[i+1];
var promisifiedKey = key + suffix;
if (promisifier === makeNodePromisified) {
obj[promisifiedKey] =
makeNodePromisified(key, THIS, key, fn, suffix, multiArgs);
} else {
var promisified = promisifier(fn, function() {
return makeNodePromisified(key, THIS, key,
fn, suffix, multiArgs);
});
util.notEnumerableProp(promisified, "__isPromisified__", true);
obj[promisifiedKey] = promisified;
}
}
util.toFastProperties(obj);
return obj;
}
function promisify(callback, receiver, multiArgs) {
return makeNodePromisified(callback, receiver, undefined,
callback, null, multiArgs);
}
Promise.promisify = function (fn, options) {
if (typeof fn !== "function") {
throw new TypeError(FUNCTION_ERROR + util.classString(fn));
}
if (isPromisified(fn)) {
return fn;
}
options = Object(options);
var receiver = options.context === undefined ? THIS : options.context;
var multiArgs = !!options.multiArgs;
var ret = promisify(fn, receiver, multiArgs);
util.copyDescriptors(fn, ret, propsFilter);
return ret;
};
Promise.promisifyAll = function (target, options) {
if (typeof target !== "function" && typeof target !== "object") {
throw new TypeError(PROMISIFY_TYPE_ERROR);
}
options = Object(options);
var multiArgs = !!options.multiArgs;
var suffix = options.suffix;
if (typeof suffix !== "string") suffix = defaultSuffix;
var filter = options.filter;
if (typeof filter !== "function") filter = defaultFilter;
var promisifier = options.promisifier;
if (typeof promisifier !== "function") promisifier = makeNodePromisified;
if (!util.isIdentifier(suffix)) {
throw new RangeError(SUFFIX_NOT_IDENTIFIER);
}
var keys = util.inheritedDataKeys(target);
for (var i = 0; i < keys.length; ++i) {
var value = target[keys[i]];
if (keys[i] !== "constructor" &&
util.isClass(value)) {
promisifyAll(value.prototype, suffix, filter, promisifier,
multiArgs);
promisifyAll(value, suffix, filter, promisifier, multiArgs);
}
}
return promisifyAll(target, suffix, filter, promisifier, multiArgs);
};
};
================================================
FILE: src/props.js
================================================
"use strict";
module.exports = function(
Promise, PromiseArray, tryConvertToPromise, apiRejection) {
var ASSERT = require("./assert");
var util = require("./util");
var isObject = util.isObject;
var es5 = require("./es5");
var Es6Map;
if (typeof Map === "function") Es6Map = Map;
var mapToEntries = (function() {
var index = 0;
var size = 0;
function extractEntry(value, key) {
this[index] = value;
this[index + size] = key;
index++;
}
return function mapToEntries(map) {
size = map.size;
index = 0;
var ret = new Array(map.size * 2);
map.forEach(extractEntry, ret);
return ret;
};
})();
var entriesToMap = function(entries) {
var ret = new Es6Map();
var length = entries.length / 2 | 0;
for (var i = 0; i < length; ++i) {
var key = entries[length + i];
var value = entries[i];
ret.set(key, value);
}
return ret;
};
function PropertiesPromiseArray(obj) {
var isMap = false;
var entries;
if (Es6Map !== undefined && obj instanceof Es6Map) {
entries = mapToEntries(obj);
isMap = true;
} else {
var keys = es5.keys(obj);
var len = keys.length;
entries = new Array(len * 2);
for (var i = 0; i < len; ++i) {
var key = keys[i];
entries[i] = obj[key];
entries[i + len] = key;
}
}
this.constructor$(entries);
this._isMap = isMap;
this._init$(undefined, isMap ? RESOLVE_MAP : RESOLVE_OBJECT);
}
util.inherits(PropertiesPromiseArray, PromiseArray);
//Override
PropertiesPromiseArray.prototype._init = function () {};
//Override
PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) {
ASSERT(!this._isResolved());
ASSERT(!(value instanceof Promise));
this._values[index] = value;
var totalResolved = ++this._totalResolved;
if (totalResolved >= this._length) {
var val;
if (this._isMap) {
val = entriesToMap(this._values);
} else {
val = {};
var keyOffset = this.length();
for (var i = 0, len = this.length(); i < len; ++i) {
val[this._values[i + keyOffset]] = this._values[i];
}
}
this._resolve(val);
return true;
}
return false;
};
// Override
PropertiesPromiseArray.prototype.shouldCopyValues = function () {
return false;
};
// Override
PropertiesPromiseArray.prototype.getActualLength = function (len) {
return len >> 1;
};
function props(promises) {
var ret;
var castValue = tryConvertToPromise(promises);
if (!isObject(castValue)) {
return apiRejection(PROPS_TYPE_ERROR);
} else if (castValue instanceof Promise) {
ret = castValue._then(
Promise.props, undefined, undefined, undefined, undefined);
} else {
ret = new PropertiesPromiseArray(castValue).promise();
}
if (castValue instanceof Promise) {
ret._propagateFrom(castValue, PROPAGATE_BIND);
}
return ret;
}
Promise.prototype.props = function () {
return props(this);
};
Promise.props = function (promises) {
return props(promises);
};
};
================================================
FILE: src/queue.js
================================================
"use strict";
var ASSERT = require("./assert");
function arrayMove(src, srcIndex, dst, dstIndex, len) {
for (var j = 0; j < len; ++j) {
dst[j + dstIndex] = src[j + srcIndex];
src[j + srcIndex] = void 0;
}
}
function Queue(capacity) {
this._capacity = capacity;
this._length = 0;
this._front = 0;
}
Queue.prototype._willBeOverCapacity = function (size) {
return this._capacity < size;
};
Queue.prototype._pushOne = function (arg) {
var length = this.length();
this._checkCapacity(length + 1);
var i = (this._front + length) & (this._capacity - 1);
this[i] = arg;
this._length = length + 1;
};
Queue.prototype.push = function (fn, receiver, arg) {
ASSERT(arguments.length === 3);
ASSERT(typeof fn === "function");
var length = this.length() + 3;
if (this._willBeOverCapacity(length)) {
//The fast array copies expect the
//underlying array to be filled completely
this._pushOne(fn);
this._pushOne(receiver);
this._pushOne(arg);
return;
}
var j = this._front + length - 3;
this._checkCapacity(length);
var wrapMask = this._capacity - 1;
this[(j + 0) & wrapMask] = fn;
this[(j + 1) & wrapMask] = receiver;
this[(j + 2) & wrapMask] = arg;
this._length = length;
};
Queue.prototype.shift = function () {
ASSERT(this.length() > 0);
var front = this._front,
ret = this[front];
this[front] = undefined;
this._front = (front + 1) & (this._capacity - 1);
this._length--;
return ret;
};
Queue.prototype.length = function () {
return this._length;
};
Queue.prototype._checkCapacity = function (size) {
if (this._capacity < size) {
this._resizeTo(this._capacity << 1);
}
};
Queue.prototype._resizeTo = function (capacity) {
var oldCapacity = this._capacity;
this._capacity = capacity;
var front = this._front;
var length = this._length;
var moveItemsCount = (front + length) & (oldCapacity - 1);
arrayMove(this, 0, this, oldCapacity, moveItemsCount);
};
module.exports = Queue;
================================================
FILE: src/race.js
================================================
"use strict";
module.exports = function(
Promise, INTERNAL, tryConvertToPromise, apiRejection) {
var util = require("./util");
var raceLater = function (promise) {
return promise.then(function(array) {
return race(array, promise);
});
};
function race(promises, parent) {
var maybePromise = tryConvertToPromise(promises);
if (maybePromise instanceof Promise) {
return raceLater(maybePromise);
} else {
promises = util.asArray(promises);
if (promises === null)
return apiRejection(COLLECTION_ERROR + util.classString(promises));
}
var ret = new Promise(INTERNAL);
if (parent !== undefined) {
ret._propagateFrom(parent, PROPAGATE_ALL);
}
var fulfill = ret._fulfill;
var reject = ret._reject;
for (var i = 0, len = promises.length; i < len; ++i) {
var val = promises[i];
if (val === undefined && !(i in promises)) {
continue;
}
Promise.cast(val)._then(fulfill, reject, undefined, ret, null);
}
//Yes, if promises were empty, it will be forever pending :-)
return ret;
}
Promise.race = function (promises) {
return race(promises, undefined);
};
Promise.prototype.race = function () {
return race(this, undefined);
};
};
================================================
FILE: src/reduce.js
================================================
"use strict";
module.exports = function(Promise,
PromiseArray,
apiRejection,
tryConvertToPromise,
INTERNAL,
debug) {
var util = require("./util");
var tryCatch = util.tryCatch;
function ReductionPromiseArray(promises, fn, initialValue, _each) {
this.constructor$(promises);
var context = Promise._getContext();
this._fn = util.contextBind(context, fn);
if (initialValue !== undefined) {
initialValue = Promise.resolve(initialValue);
initialValue._attachCancellationCallback(this);
}
this._initialValue = initialValue;
this._currentCancellable = null;
if(_each === INTERNAL) {
this._eachValues = Array(this._length);
} else if (_each === 0) {
this._eachValues = null;
} else {
this._eachValues = undefined;
}
this._promise._captureStackTrace();
this._init$(undefined, RESOLVE_CALL_METHOD);
}
util.inherits(ReductionPromiseArray, PromiseArray);
ReductionPromiseArray.prototype._gotAccum = function(accum) {
if (this._eachValues !== undefined &&
this._eachValues !== null &&
accum !== INTERNAL) {
this._eachValues.push(accum);
}
};
ReductionPromiseArray.prototype._eachComplete = function(value) {
if (this._eachValues !== null) {
this._eachValues.push(value);
}
return this._eachValues;
};
// Override
ReductionPromiseArray.prototype._init = function() {};
// Override
ReductionPromiseArray.prototype._resolveEmptyArray = function() {
this._resolve(this._eachValues !== undefined ? this._eachValues
: this._initialValue);
};
// Override
ReductionPromiseArray.prototype.shouldCopyValues = function () {
return false;
};
// Override
ReductionPromiseArray.prototype._resolve = function(value) {
this._promise._resolveCallback(value);
this._values = null;
};
// Override
ReductionPromiseArray.prototype._resultCancelled = function(sender) {
if (sender === this._initialValue) return this._cancel();
if (this._isResolved()) return;
this._resultCancelled$();
if (this._currentCancellable instanceof Promise) {
this._currentCancellable.cancel();
}
if (this._initialValue instanceof Promise) {
this._initialValue.cancel();
}
};
// Override
ReductionPromiseArray.prototype._iterate = function (values) {
this._values = values;
var value;
var i;
var length = values.length;
if (this._initialValue !== undefined) {
value = this._initialValue;
i = 0;
} else {
value = Promise.resolve(values[0]);
i = 1;
}
this._currentCancellable = value;
for (var j = i; j < length; ++j) {
var maybePromise = values[j];
if (maybePromise instanceof Promise) {
maybePromise.suppressUnhandledRejections();
}
}
if (!value.isRejected()) {
for (; i < length; ++i) {
var ctx = {
accum: null,
value: values[i],
index: i,
length: length,
array: this
};
value = value._then(gotAccum, undefined, undefined, ctx, undefined);
// Too many promises chained with asyncGuaranteed will result in
// stack overflow. Break up long chains to reset stack.
if ((i & 127) === 0) {
value._setNoAsyncGuarantee();
}
}
}
if (this._eachValues !== undefined) {
value = value
._then(this._eachComplete, undefined, undefined, this, undefined);
}
value._then(completed, completed, undefined, value, this);
};
Promise.prototype.reduce = function (fn, initialValue) {
return reduce(this, fn, initialValue, null);
};
Promise.reduce = function (promises, fn, initialValue, _each) {
return reduce(promises, fn, initialValue, _each);
};
function completed(valueOrReason, array) {
if (this.isFulfilled()) {
array._resolve(valueOrReason);
} else {
array._reject(valueOrReason);
}
}
function reduce(promises, fn, initialValue, _each) {
if (typeof fn !== "function") {
return apiRejection(FUNCTION_ERROR + util.classString(fn));
}
var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
return array.promise();
}
function gotAccum(accum) {
this.accum = accum;
this.array._gotAccum(accum);
var value = tryConvertToPromise(this.value, this.array._promise);
if (value instanceof Promise) {
this.array._currentCancellable = value;
return value._then(gotValue, undefined, undefined, this, undefined);
} else {
return gotValue.call(this, value);
}
}
function gotValue(value) {
var array = this.array;
var promise = array._promise;
var fn = tryCatch(array._fn);
promise._pushContext();
var ret;
if (array._eachValues !== undefined) {
ret = fn.call(promise._boundValue(), value, this.index, this.length);
} else {
ret = fn.call(promise._boundValue(),
this.accum, value, this.index, this.length);
}
if (ret instanceof Promise) {
array._currentCancellable = ret;
}
var promiseCreated = promise._popContext();
debug.checkForgottenReturns(
ret,
promiseCreated,
array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",
promise
);
return ret;
}
};
================================================
FILE: src/schedule.js
================================================
"use strict";
var util = require("./util");
var schedule;
var noAsyncScheduler = function() {
throw new Error(NO_ASYNC_SCHEDULER);
};
var NativePromise = util.getNativePromise();
// This file figures out which scheduler to use for Bluebird. It normalizes
// async task scheduling across target platforms. Note that not all JS target
// platforms come supported. The scheduler is overridable with `setScheduler`.
// Our scheduler for Node.js/io.js is setImmediate for recent
// versions of node because of macrotask semantics.
// The `typeof` check is for an edge case with nw.js.
if (util.isNode && typeof MutationObserver === "undefined") {
var GlobalSetImmediate = global.setImmediate;
var ProcessNextTick = process.nextTick;
schedule = util.isRecentNode
? function(fn) { GlobalSetImmediate.call(global, fn); }
: function(fn) { ProcessNextTick.call(process, fn); };
} else if (typeof NativePromise === "function" &&
typeof NativePromise.resolve === "function") {
var nativePromise = NativePromise.resolve();
schedule = function(fn) {
nativePromise.then(fn);
};
// Outside of Node, we're using MutationObservers because they provide low
// latency. The second check is to guard against iOS standalone apps which
// do not fire DOM mutation events for some reason on iOS 8.3+ and cordova
// apps which have the same bug but are not `.navigator.standalone`
} else if ((typeof MutationObserver !== "undefined") &&
!(typeof window !== "undefined" &&
window.navigator &&
(window.navigator.standalone || window.cordova)) &&
("classList" in document.documentElement)) {
schedule = (function() {
// Using 2 mutation observers to batch multiple updates into one.
var div = document.createElement("div");
var opts = {attributes: true};
var toggleScheduled = false;
var div2 = document.createElement("div");
var o2 = new MutationObserver(function() {
div.classList.toggle("foo");
toggleScheduled = false;
});
o2.observe(div2, opts);
var scheduleToggle = function() {
if (toggleScheduled) return;
toggleScheduled = true;
div2.classList.toggle("foo");
};
return function schedule(fn) {
var o = new MutationObserver(function() {
o.disconnect();
fn();
});
o.observe(div, opts);
scheduleToggle();
};
})();
// setImmediate has higher latency but is still pretty good. This is useful for
// cases where MutationObserver is not defined (older IE, for example).
} else if (typeof setImmediate !== "undefined") {
schedule = function (fn) {
setImmediate(fn);
};
// setTimeout also works, it has the most latency but it does the trick.
} else if (typeof setTimeout !== "undefined") {
schedule = function (fn) {
setTimeout(fn, 0);
};
} else {
// Do __Not__ default to a sync scheduler, that would break Promises/A+
// compliancy and cause race conditions.
schedule = noAsyncScheduler;
}
module.exports = schedule;
================================================
FILE: src/settle.js
================================================
"use strict";
module.exports =
function(Promise, PromiseArray, debug) {
var ASSERT = require("./assert");
var PromiseInspection = Promise.PromiseInspection;
var util = require("./util");
function SettledPromiseArray(values) {
this.constructor$(values);
}
util.inherits(SettledPromiseArray, PromiseArray);
SettledPromiseArray.prototype._promiseResolved = function (index, inspection) {
ASSERT(typeof index === "number");
this._values[index] = inspection;
var totalResolved = ++this._totalResolved;
if (totalResolved >= this._length) {
this._resolve(this._values);
return true;
}
return false;
};
//override
SettledPromiseArray.prototype._promiseFulfilled = function (value, index) {
ASSERT(!this._isResolved());
ASSERT(typeof index === "number");
var ret = new PromiseInspection();
ret._bitField = IS_FULFILLED;
ret._settledValueField = value;
return this._promiseResolved(index, ret);
};
//override
SettledPromiseArray.prototype._promiseRejected = function (reason, index) {
ASSERT(!this._isResolved());
ASSERT(typeof index === "number");
var ret = new PromiseInspection();
ret._bitField = IS_REJECTED;
ret._settledValueField = reason;
return this._promiseResolved(index, ret);
};
Promise.settle = function (promises) {
debug.deprecated(".settle()", ".reflect()");
return new SettledPromiseArray(promises).promise();
};
Promise.allSettled = function (promises) {
return new SettledPromiseArray(promises).promise();
};
Promise.prototype.settle = function () {
return Promise.settle(this);
};
};
================================================
FILE: src/some.js
================================================
"use strict";
module.exports =
function(Promise, PromiseArray, apiRejection) {
var ASSERT = require("./assert");
var util = require("./util");
var RangeError = require("./errors").RangeError;
var AggregateError = require("./errors").AggregateError;
var isArray = util.isArray;
var CANCELLATION = {};
function SomePromiseArray(values) {
this.constructor$(values);
this._howMany = 0;
this._unwrap = false;
this._initialized = false;
}
util.inherits(SomePromiseArray, PromiseArray);
SomePromiseArray.prototype._init = function () {
if (!this._initialized) {
return;
}
if (this._howMany === 0) {
this._resolve([]);
return;
}
this._init$(undefined, RESOLVE_CALL_METHOD);
var isArrayResolved = isArray(this._values);
if (!this._isResolved() &&
isArrayResolved &&
this._howMany > this._canPossiblyFulfill()) {
this._reject(this._getRangeError(this.length()));
}
};
SomePromiseArray.prototype.init = function () {
this._initialized = true;
this._init();
};
SomePromiseArray.prototype.setUnwrap = function () {
this._unwrap = true;
};
SomePromiseArray.prototype.howMany = function () {
return this._howMany;
};
SomePromiseArray.prototype.setHowMany = function (count) {
ASSERT(!this._isResolved());
this._howMany = count;
};
//override
SomePromiseArray.prototype._promiseFulfilled = function (value) {
ASSERT(!this._isResolved());
this._addFulfilled(value);
if (this._fulfilled() === this.howMany()) {
this._values.length = this.howMany();
if (this.howMany() === 1 && this._unwrap) {
this._resolve(this._values[0]);
} else {
this._resolve(this._values);
}
return true;
}
return false;
};
//override
SomePromiseArray.prototype._promiseRejected = function (reason) {
ASSERT(!this._isResolved());
this._addRejected(reason);
return this._checkOutcome();
};
//override
SomePromiseArray.prototype._promiseCancelled = function () {
if (this._values instanceof Promise || this._values == null) {
return this._cancel();
}
ASSERT(!this._isResolved());
this._addRejected(CANCELLATION);
return this._checkOutcome();
};
SomePromiseArray.prototype._checkOutcome = function() {
if (this.howMany() > this._canPossiblyFulfill()) {
var e = new AggregateError();
for (var i = this.length(); i < this._values.length; ++i) {
if (this._values[i] !== CANCELLATION) {
e.push(this._values[i]);
}
}
if (e.length > 0) {
this._reject(e);
} else {
this._cancel();
}
return true;
}
return false;
};
SomePromiseArray.prototype._fulfilled = function () {
return this._totalResolved;
};
SomePromiseArray.prototype._rejected = function () {
return this._values.length - this.length();
};
//Use the same array past .length() to store rejection reasons
SomePromiseArray.prototype._addRejected = function (reason) {
this._values.push(reason);
};
SomePromiseArray.prototype._addFulfilled = function (value) {
this._values[this._totalResolved++] = value;
};
SomePromiseArray.prototype._canPossiblyFulfill = function () {
return this.length() - this._rejected();
};
SomePromiseArray.prototype._getRangeError = function (count) {
var message = "Input array must contain at least " +
this._howMany + " items but contains only " + count + " items";
return new RangeError(message);
};
SomePromiseArray.prototype._resolveEmptyArray = function () {
this._reject(this._getRangeError(0));
};
function some(promises, howMany) {
if ((howMany | 0) !== howMany || howMany < 0) {
return apiRejection(POSITIVE_INTEGER_ERROR);
}
var ret = new SomePromiseArray(promises);
var promise = ret.promise();
ASSERT(promise.isPending());
ASSERT(ret instanceof SomePromiseArray);
ret.setHowMany(howMany);
ret.init();
return promise;
}
Promise.some = function (promises, howMany) {
return some(promises, howMany);
};
Promise.prototype.some = function (howMany) {
return some(this, howMany);
};
Promise._SomePromiseArray = SomePromiseArray;
};
================================================
FILE: src/synchronous_inspection.js
================================================
"use strict";
module.exports = function(Promise) {
function PromiseInspection(promise) {
if (promise !== undefined) {
promise = promise._target();
this._bitField = promise._bitField;
this._settledValueField = promise._isFateSealed()
? promise._settledValue() : undefined;
}
else {
this._bitField = 0;
this._settledValueField = undefined;
}
}
PromiseInspection.prototype._settledValue = function() {
return this._settledValueField;
};
var value = PromiseInspection.prototype.value = function () {
if (!this.isFulfilled()) {
throw new TypeError(INSPECTION_VALUE_ERROR);
}
return this._settledValue();
};
var reason = PromiseInspection.prototype.error =
PromiseInspection.prototype.reason = function () {
if (!this.isRejected()) {
throw new TypeError(INSPECTION_REASON_ERROR);
}
return this._settledValue();
};
var isFulfilled = PromiseInspection.prototype.isFulfilled = function() {
return (this._bitField & IS_FULFILLED) !== 0;
};
var isRejected = PromiseInspection.prototype.isRejected = function () {
return (this._bitField & IS_REJECTED) !== 0;
};
var isPending = PromiseInspection.prototype.isPending = function () {
return (this._bitField & IS_REJECTED_OR_FULFILLED_OR_CANCELLED) === 0;
};
var isResolved = PromiseInspection.prototype.isResolved = function () {
return (this._bitField & IS_REJECTED_OR_FULFILLED) !== 0;
};
PromiseInspection.prototype.isCancelled = function() {
return (this._bitField & IS_CANCELLED_OR_WILL_BE_CANCELLED) !== 0;
};
Promise.prototype.__isCancelled = function() {
return (this._bitField & IS_CANCELLED) === IS_CANCELLED;
};
Promise.prototype._isCancelled = function() {
return this._target().__isCancelled();
};
Promise.prototype.isCancelled = function() {
return (this._target()._bitField & IS_CANCELLED_OR_WILL_BE_CANCELLED) !== 0;
};
Promise.prototype.isPending = function() {
return isPending.call(this._target());
};
Promise.prototype.isRejected = function() {
return isRejected.call(this._target());
};
Promise.prototype.isFulfilled = function() {
return isFulfilled.call(this._target());
};
Promise.prototype.isResolved = function() {
return isResolved.call(this._target());
};
Promise.prototype.value = function() {
return value.call(this._target());
};
Promise.prototype.reason = function() {
var target = this._target();
target._unsetRejectionIsUnhandled();
return reason.call(target);
};
Promise.prototype._value = function() {
return this._settledValue();
};
Promise.prototype._reason = function() {
this._unsetRejectionIsUnhandled();
return this._settledValue();
};
Promise.PromiseInspection = PromiseInspection;
};
================================================
FILE: src/thenables.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL) {
var ASSERT = require("./assert");
var util = require("./util");
var errorObj = util.errorObj;
var isObject = util.isObject;
function tryConvertToPromise(obj, context) {
if (isObject(obj)) {
if (obj instanceof Promise) return obj;
var then = getThen(obj);
if (then === errorObj) {
if (context) context._pushContext();
var ret = Promise.reject(then.e);
if (context) context._popContext();
return ret;
} else if (typeof then === "function") {
//Make casting from another bluebird fast
if (isAnyBluebirdPromise(obj)) {
var ret = new Promise(INTERNAL);
obj._then(
ret._fulfill,
ret._reject,
undefined,
ret,
null
);
return ret;
}
return doThenable(obj, then, context);
}
}
return obj;
}
function doGetThen(obj) {
return obj.then;
}
function getThen(obj) {
try {
return doGetThen(obj);
} catch (e) {
errorObj.e = e;
return errorObj;
}
}
var hasProp = {}.hasOwnProperty;
function isAnyBluebirdPromise(obj) {
try {
return hasProp.call(obj, "_promise0");
} catch (e) {
return false;
}
}
function doThenable(x, then, context) {
ASSERT(typeof then === "function");
var promise = new Promise(INTERNAL);
var ret = promise;
if (context) context._pushContext();
promise._captureStackTrace();
if (context) context._popContext();
var synchronous = true;
var result = util.tryCatch(then).call(x, resolve, reject);
synchronous = false;
if (promise && result === errorObj) {
promise._rejectCallback(result.e, true, true);
promise = null;
}
function resolve(value) {
if (!promise) return;
promise._resolveCallback(value);
promise = null;
}
function reject(reason) {
if (!promise) return;
promise._rejectCallback(reason, synchronous, true);
promise = null;
}
return ret;
}
return tryConvertToPromise;
};
================================================
FILE: src/timers.js
================================================
"use strict";
module.exports = function(Promise, INTERNAL, debug) {
var util = require("./util");
var TimeoutError = Promise.TimeoutError;
function HandleWrapper(handle) {
this.handle = handle;
}
HandleWrapper.prototype._resultCancelled = function() {
clearTimeout(this.handle);
};
var afterValue = function(value) { return delay(+this).thenReturn(value); };
var delay = Promise.delay = function (ms, value) {
var ret;
var handle;
if (value !== undefined) {
ret = Promise.resolve(value)
._then(afterValue, null, null, ms, undefined);
if (debug.cancellation() && value instanceof Promise) {
ret._setOnCancel(value);
}
} else {
ret = new Promise(INTERNAL);
handle = setTimeout(function() { ret._fulfill(); }, +ms);
if (debug.cancellation()) {
ret._setOnCancel(new HandleWrapper(handle));
}
ret._captureStackTrace();
}
ret._setAsyncGuaranteed();
return ret;
};
Promise.prototype.delay = function (ms) {
return delay(ms, this);
};
var afterTimeout = function (promise, message, parent) {
var err;
if (typeof message !== "string") {
if (message instanceof Error) {
err = message;
} else {
err = new TimeoutError(TIMEOUT_ERROR);
}
} else {
err = new TimeoutError(message);
}
util.markAsOriginatingFromRejection(err);
promise._attachExtraTrace(err);
promise._reject(err);
if (parent != null) {
parent.cancel();
}
};
function successClear(value) {
clearTimeout(this.handle);
return value;
}
function failureClear(reason) {
clearTimeout(this.handle);
throw reason;
}
Promise.prototype.timeout = function (ms, message) {
ms = +ms;
var ret, parent;
var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() {
if (ret.isPending()) {
afterTimeout(ret, message, parent);
}
}, ms));
if (debug.cancellation()) {
parent = this.then();
ret = parent._then(successClear, failureClear,
undefined, handleWrapper, undefined);
ret._setOnCancel(handleWrapper);
} else {
ret = this._then(successClear, failureClear,
undefined, handleWrapper, undefined);
}
return ret;
};
};
================================================
FILE: src/using.js
================================================
"use strict";
module.exports = function (Promise, apiRejection, tryConvertToPromise,
createContext, INTERNAL, debug) {
var util = require("./util");
var TypeError = require("./errors").TypeError;
var inherits = require("./util").inherits;
var errorObj = util.errorObj;
var tryCatch = util.tryCatch;
var NULL = {};
function thrower(e) {
setTimeout(function(){throw e;}, 0);
}
function castPreservingDisposable(thenable) {
var maybePromise = tryConvertToPromise(thenable);
if (maybePromise !== thenable &&
typeof thenable._isDisposable === "function" &&
typeof thenable._getDisposer === "function" &&
thenable._isDisposable()) {
maybePromise._setDisposable(thenable._getDisposer());
}
return maybePromise;
}
function dispose(resources, inspection) {
var i = 0;
var len = resources.length;
var ret = new Promise(INTERNAL);
function iterator() {
if (i >= len) return ret._fulfill();
var maybePromise = castPreservingDisposable(resources[i++]);
if (maybePromise instanceof Promise &&
maybePromise._isDisposable()) {
try {
maybePromise = tryConvertToPromise(
maybePromise._getDisposer().tryDispose(inspection),
resources.promise);
} catch (e) {
return thrower(e);
}
if (maybePromise instanceof Promise) {
return maybePromise._then(iterator, thrower,
null, null, null);
}
}
iterator();
}
iterator();
return ret;
}
function Disposer(data, promise, context) {
this._data = data;
this._promise = promise;
this._context = context;
}
Disposer.prototype.data = function () {
return this._data;
};
Disposer.prototype.promise = function () {
return this._promise;
};
Disposer.prototype.resource = function () {
if (this.promise().isFulfilled()) {
return this.promise().value();
}
return NULL;
};
Disposer.prototype.tryDispose = function(inspection) {
var resource = this.resource();
var context = this._context;
if (context !== undefined) context._pushContext();
var ret = resource !== NULL
? this.doDispose(resource, inspection) : null;
if (context !== undefined) context._popContext();
this._promise._unsetDisposable();
this._data = null;
return ret;
};
Disposer.isDisposer = function (d) {
return (d != null &&
typeof d.resource === "function" &&
typeof d.tryDispose === "function");
};
function FunctionDisposer(fn, promise, context) {
this.constructor$(fn, promise, context);
}
inherits(FunctionDisposer, Disposer);
FunctionDisposer.prototype.doDispose = function (resource, inspection) {
var fn = this.data();
return fn.call(resource, resource, inspection);
};
function maybeUnwrapDisposer(value) {
if (Disposer.isDisposer(value)) {
this.resources[this.index]._setDisposable(value);
return value.promise();
}
return value;
}
function ResourceList(length) {
this.length = length;
this.promise = null;
this[length-1] = null;
}
ResourceList.prototype._resultCancelled = function() {
var len = this.length;
for (var i = 0; i < len; ++i) {
var item = this[i];
if (item instanceof Promise) {
item.cancel();
}
}
};
Promise.using = function () {
var len = arguments.length;
if (len < 2) return apiRejection(
"you must pass at least 2 arguments to Promise.using");
var fn = arguments[len - 1];
if (typeof fn !== "function") {
return apiRejection(FUNCTION_ERROR + util.classString(fn));
}
var input;
var spreadArgs = true;
if (len === 2 && Array.isArray(arguments[0])) {
input = arguments[0];
len = input.length;
spreadArgs = false;
} else {
input = arguments;
len--;
}
var resources = new ResourceList(len);
for (var i = 0; i < len; ++i) {
var resource = input[i];
if (Disposer.isDisposer(resource)) {
var disposer = resource;
resource = resource.promise();
resource._setDisposable(disposer);
} else {
var maybePromise = tryConvertToPromise(resource);
if (maybePromise instanceof Promise) {
resource =
maybePromise._then(maybeUnwrapDisposer, null, null, {
resources: resources,
index: i
}, undefined);
}
}
resources[i] = resource;
}
var reflectedResources = new Array(resources.length);
for (var i = 0; i < reflectedResources.length; ++i) {
reflectedResources[i] = Promise.resolve(resources[i]).reflect();
}
var resultPromise = Promise.all(reflectedResources)
.then(function(inspections) {
for (var i = 0; i < inspections.length; ++i) {
var inspection = inspections[i];
if (inspection.isRejected()) {
errorObj.e = inspection.error();
return errorObj;
} else if (!inspection.isFulfilled()) {
resultPromise.cancel();
return;
}
inspections[i] = inspection.value();
}
promise._pushContext();
fn = tryCatch(fn);
var ret = spreadArgs
? fn.apply(undefined, inspections) : fn(inspections);
var promiseCreated = promise._popContext();
debug.checkForgottenReturns(
ret, promiseCreated, "Promise.using", promise);
return ret;
});
var promise = resultPromise.lastly(function() {
var inspection = new Promise.PromiseInspection(resultPromise);
return dispose(resources, inspection);
});
resources.promise = promise;
promise._setOnCancel(resources);
return promise;
};
Promise.prototype._setDisposable = function (disposer) {
this._bitField = this._bitField | IS_DISPOSABLE;
this._disposer = disposer;
};
Promise.prototype._isDisposable = function () {
return (this._bitField & IS_DISPOSABLE) > 0;
};
Promise.prototype._getDisposer = function () {
return this._disposer;
};
Promise.prototype._unsetDisposable = function () {
this._bitField = this._bitField & (~IS_DISPOSABLE);
this._disposer = undefined;
};
Promise.prototype.disposer = function (fn) {
if (typeof fn === "function") {
return new FunctionDisposer(fn, this, createContext());
}
throw new TypeError();
};
};
================================================
FILE: src/util.js
================================================
"use strict";
var ASSERT = require("./assert");
var es5 = require("./es5");
// Assume CSP if browser
var canEvaluate = typeof navigator == "undefined";
//Try catch is not supported in optimizing
//compiler, so it is isolated
var errorObj = {e: {}};
var tryCatchTarget;
var globalObject = typeof self !== "undefined" ? self :
typeof window !== "undefined" ? window :
typeof global !== "undefined" ? global :
this !== undefined ? this : null;
function tryCatcher() {
try {
var target = tryCatchTarget;
tryCatchTarget = null;
return target.apply(this, arguments);
} catch (e) {
errorObj.e = e;
return errorObj;
}
}
function tryCatch(fn) {
ASSERT(typeof fn === "function");
tryCatchTarget = fn;
return tryCatcher;
}
//Un-magical enough that using this doesn't prevent
//extending classes from outside using any convention
var inherits = function(Child, Parent) {
var hasProp = {}.hasOwnProperty;
function T() {
this.constructor = Child;
this.constructor$ = Parent;
for (var propertyName in Parent.prototype) {
if (hasProp.call(Parent.prototype, propertyName) &&
propertyName.charAt(propertyName.length-1) !== "$"
) {
this[propertyName + "$"] = Parent.prototype[propertyName];
}
}
}
T.prototype = Parent.prototype;
Child.prototype = new T();
return Child.prototype;
};
function isPrimitive(val) {
return val == null || val === true || val === false ||
typeof val === "string" || typeof val === "number";
}
function isObject(value) {
return typeof value === "function" ||
typeof value === "object" && value !== null;
}
function maybeWrapAsError(maybeError) {
if (!isPrimitive(maybeError)) return maybeError;
return new Error(safeToString(maybeError));
}
function withAppended(target, appendee) {
var len = target.length;
var ret = new Array(len + 1);
var i;
for (i = 0; i < len; ++i) {
ret[i] = target[i];
}
ret[i] = appendee;
return ret;
}
function getDataPropertyOrDefault(obj, key, defaultValue) {
if (es5.isES5) {
var desc = Object.getOwnPropertyDescriptor(obj, key);
if (desc != null) {
return desc.get == null && desc.set == null
? desc.value
: defaultValue;
}
} else {
return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined;
}
}
function notEnumerableProp(obj, name, value) {
if (isPrimitive(obj)) return obj;
var descriptor = {
value: value,
configurable: true,
enumerable: false,
writable: true
};
es5.defineProperty(obj, name, descriptor);
return obj;
}
function thrower(r) {
throw r;
}
var inheritedDataKeys = (function() {
var excludedPrototypes = [
Array.prototype,
Object.prototype,
Function.prototype
];
var isExcludedProto = function(val) {
for (var i = 0; i < excludedPrototypes.length; ++i) {
if (excludedPrototypes[i] === val) {
return true;
}
}
return false;
};
if (es5.isES5) {
var getKeys = Object.getOwnPropertyNames;
return function(obj) {
var ret = [];
var visitedKeys = Object.create(null);
while (obj != null && !isExcludedProto(obj)) {
var keys;
try {
keys = getKeys(obj);
} catch (e) {
return ret;
}
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
if (visitedKeys[key]) continue;
visitedKeys[key] = true;
var desc = Object.getOwnPropertyDescriptor(obj, key);
if (desc != null && desc.get == null && desc.set == null) {
ret.push(key);
}
}
obj = es5.getPrototypeOf(obj);
}
return ret;
};
} else {
var hasProp = {}.hasOwnProperty;
return function(obj) {
if (isExcludedProto(obj)) return [];
var ret = [];
/*jshint forin:false */
enumeration: for (var key in obj) {
if (hasProp.call(obj, key)) {
ret.push(key);
} else {
for (var i = 0; i < excludedPrototypes.length; ++i) {
if (hasProp.call(excludedPrototypes[i], key)) {
continue enumeration;
}
}
ret.push(key);
}
}
return ret;
};
}
})();
var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/;
function isClass(fn) {
try {
if (typeof fn === "function") {
var keys = es5.names(fn.prototype);
var hasMethods = es5.isES5 && keys.length > 1;
var hasMethodsOtherThanConstructor = keys.length > 0 &&
!(keys.length === 1 && keys[0] === "constructor");
var hasThisAssignmentAndStaticMethods =
thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0;
if (hasMethods || hasMethodsOtherThanConstructor ||
hasThisAssignmentAndStaticMethods) {
return true;
}
}
return false;
} catch (e) {
return false;
}
}
var fastProto = null;
var kInlineCacheCutoff = 10;
function FastObject(o) {
if (fastProto !== null && typeof fastProto.property) {
var result = fastProto;
fastProto = FastObject.prototype = null;
return result;
}
fastProto = FastObject.prototype = o == null ? Object.create(null) : o;
return new FastObject();
}
// Initialize the inline property cache of FastObject
for(var i = 0; i <= kInlineCacheCutoff; i++) {
FastObject({});
}
function toFastProperties(obj) {
FastObject(obj);
ASSERT("%HasFastProperties", true, obj);
return obj;
}
var rident = /^[a-z$_][a-z$_0-9]*$/i;
function isIdentifier(str) {
return rident.test(str);
}
function filledRange(count, prefix, suffix) {
var ret = new Array(count);
for(var i = 0; i < count; ++i) {
ret[i] = prefix + i + suffix;
}
return ret;
}
function safeToString(obj) {
try {
return obj + "";
} catch (e) {
return "[no string representation]";
}
}
function isError(obj) {
return obj instanceof Error ||
(obj !== null &&
typeof obj === "object" &&
typeof obj.message === "string" &&
typeof obj.name === "string");
}
function markAsOriginatingFromRejection(e) {
try {
notEnumerableProp(e, OPERATIONAL_ERROR_KEY, true);
}
catch(ignore) {}
}
function originatesFromRejection(e) {
if (e == null) return false;
return ((e instanceof Error[BLUEBIRD_ERRORS].OperationalError) ||
e[OPERATIONAL_ERROR_KEY] === true);
}
function canAttachTrace(obj) {
return isError(obj) && es5.propertyIsWritable(obj, "stack");
}
var ensureErrorObject = (function() {
if (!("stack" in new Error())) {
return function(value) {
if (canAttachTrace(value)) return value;
try {throw new Error(safeToString(value));}
catch(err) {return err;}
};
} else {
return function(value) {
if (canAttachTrace(value)) return value;
return new Error(safeToString(value));
};
}
})();
function classString(obj) {
return {}.toString.call(obj);
}
function copyDescriptors(from, to, filter) {
var keys = es5.names(from);
for (var i = 0; i < keys.length; ++i) {
var key = keys[i];
if (filter(key)) {
try {
es5.defineProperty(to, key, es5.getDescriptor(from, key));
} catch (ignore) {}
}
}
}
var asArray = function(v) {
if (es5.isArray(v)) {
return v;
}
return null;
};
if (typeof Symbol !== "undefined" && Symbol.iterator) {
var ArrayFrom = typeof Array.from === "function" ? function(v) {
return Array.from(v);
} : function(v) {
var ret = [];
var it = v[Symbol.iterator]();
var itResult;
while (!((itResult = it.next()).done)) {
ret.push(itResult.value);
}
return ret;
};
asArray = function(v) {
if (es5.isArray(v)) {
return v;
} else if (v != null && typeof v[Symbol.iterator] === "function") {
return ArrayFrom(v);
}
return null;
};
}
var isNode = typeof process !== "undefined" &&
classString(process).toLowerCase() === "[object process]";
var hasEnvVariables = typeof process !== "undefined" &&
typeof process.env !== "undefined";
function env(key) {
return hasEnvVariables ? process.env[key] : undefined;
}
function getNativePromise() {
if (typeof Promise === "function") {
try {
var promise = new Promise(function(){});
if (classString(promise) === "[object Promise]") {
return Promise;
}
} catch (e) {}
}
}
var reflectHandler;
function contextBind(ctx, cb) {
if (ctx === null ||
typeof cb !== "function" ||
cb === reflectHandler) {
return cb;
}
if (ctx.domain !== null) {
cb = ctx.domain.bind(cb);
}
var async = ctx.async;
if (async !== null) {
var old = cb;
cb = function() {
INLINE_SLICE_LEFT_PADDED(2, args, arguments);
args[0] = old;
args[1] = this;
return async.runInAsyncScope.apply(async, args);
};
}
return cb;
}
var ret = {
setReflectHandler: function(fn) {
reflectHandler = fn;
},
isClass: isClass,
isIdentifier: isIdentifier,
inheritedDataKeys: inheritedDataKeys,
getDataPropertyOrDefault: getDataPropertyOrDefault,
thrower: thrower,
isArray: es5.isArray,
asArray: asArray,
notEnumerableProp: notEnumerableProp,
isPrimitive: isPrimitive,
isObject: isObject,
isError: isError,
canEvaluate: canEvaluate,
errorObj: errorObj,
tryCatch: tryCatch,
inherits: inherits,
withAppended: withAppended,
maybeWrapAsError: maybeWrapAsError,
toFastProperties: toFastProperties,
filledRange: filledRange,
toString: safeToString,
canAttachTrace: canAttachTrace,
ensureErrorObject: ensureErrorObject,
originatesFromRejection: originatesFromRejection,
markAsOriginatingFromRejection: markAsOriginatingFromRejection,
classString: classString,
copyDescriptors: copyDescriptors,
isNode: isNode,
hasEnvVariables: hasEnvVariables,
env: env,
global: globalObject,
getNativePromise: getNativePromise,
contextBind: contextBind
};
ret.isRecentNode = ret.isNode && (function() {
var version;
if (process.versions && process.versions.node) {
version = process.versions.node.split(".").map(Number);
} else if (process.version) {
version = process.version.split(".").map(Number);
}
return (version[0] === 0 && version[1] > 10) || (version[0] > 0);
})();
ret.nodeSupportsAsyncResource = ret.isNode && (function() {
var supportsAsync = false;
try {
var res = require("async_hooks").AsyncResource;
supportsAsync = typeof res.prototype.runInAsyncScope === "function";
} catch (e) {
supportsAsync = false;
}
return supportsAsync;
})();
if (ret.isNode) ret.toFastProperties(process);
try {throw new Error(); } catch (e) {ret.lastLineError = e;}
module.exports = ret;
================================================
FILE: test/browser/es5-sham.js
================================================
// Copyright 2009-2012 by contributors, MIT License
// vim: ts=4 sts=4 sw=4 expandtab
// Module systems magic dance
(function (definition) {
// RequireJS
if (typeof define == "function") {
define(definition);
// YUI3
} else if (typeof YUI == "function") {
YUI.add("es5-sham", definition);
// CommonJS and