...
 
Commits (8)
......@@ -147,6 +147,24 @@ getJSON("/post/1.json").then(function(post) {
});
```
## Error Handling
There are times when dealing with promises that it seems like any errors
are being 'swallowed', and not properly raised. This makes is extremely
difficult to track down where a given issue is coming from. Thankfully,
`RSVP` has a solution for this problem built in.
You can provide an `onerror` function that will be called with the error
details if any errors occur within your promise. This function can be anything
but a common practice is to call `console.assert` to dump the error to the
console.
```javascript
RSVP.configure('onerror', function(error) {
console.assert(false, error);
});
```
## Arrays of promises
Sometimes you might want to work with many promises at once. If you
......@@ -168,6 +186,31 @@ RSVP.all(promises).then(function(posts) {
});
```
## Hash of promises
If you need to reference many promises at once (like `all()`), but would like
to avoid encoding the actual promise order you can use `hash()`. If you pass
an object literal (where the values are promises) to the `hash()` method it will
return a new promise that will be fulfilled when all of the promises have been
fulfilled; or rejected immediately if any promise is rejected.
The key difference to the `all()` function is that both the fulfillment value
and the argument to the `hash()` function are object literals. This allows
you to simply reference the results directly off the returned object without
having to remember the initial order like you would with `all()`.
```javascript
var promises = {
posts: getJSON("/posts.json"),
users: getJSON("/users.json")
};
RSVP.hash(promises).then(function(results) {
console.log(results.users) // print the users.json results
console.log(results.posts) // print the posts.json results
});
```
## TaskJS
The [TaskJS](http://taskjs.org/) library makes it possible to take
......
var browserGlobal = (typeof window !== 'undefined') ? window : {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
var async;
var local = (typeof global !== 'undefined') ? global : this;
// old node
// node
function useNextTick() {
return function(callback, arg) {
process.nextTick(function() {
callback(arg);
});
};
}
// node >= 0.10.x
function useSetImmediate() {
return function(callback, arg) {
/* global setImmediate */
setImmediate(function(){
callback(arg);
});
return function() {
process.nextTick(flush);
};
}
function useMutationObserver() {
var queue = [];
var observer = new BrowserMutationObserver(function() {
var toProcess = queue.slice();
queue = [];
toProcess.forEach(function(tuple) {
var callback = tuple[0], arg= tuple[1];
callback(arg);
});
});
var observer = new BrowserMutationObserver(flush);
var element = document.createElement('div');
observer.observe(element, { attributes: true });
......@@ -44,28 +20,46 @@ function useMutationObserver() {
observer = null;
}, false);
return function(callback, arg) {
queue.push([callback, arg]);
return function() {
element.setAttribute('drainQueue', 'drainQueue');
};
}
function useSetTimeout() {
return function(callback, arg) {
local.setTimeout(function() {
callback(arg);
}, 1);
return function() {
local.setTimeout(flush, 1);
};
}
if (typeof setImmediate === 'function') {
async = useSetImmediate();
} else if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
async = useNextTick();
var queue = [];
function flush() {
for (var i = 0; i < queue.length; i++) {
var tuple = queue[i];
var callback = tuple[0], arg = tuple[1];
callback(arg);
}
queue = [];
}
var scheduleFlush;
// Decide what async method to use to triggering processing of queued callbacks:
if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') {
scheduleFlush = useNextTick();
} else if (BrowserMutationObserver) {
async = useMutationObserver();
scheduleFlush = useMutationObserver();
} else {
async = useSetTimeout();
scheduleFlush = useSetTimeout();
}
function async(callback, arg) {
var length = queue.push([callback, arg]);
if (length === 1) {
// If length is 1, that means that we need to schedule an async flush.
// If additional callbacks are queued before the queue is flushed, they
// will be processed by this flush that we are scheduling.
scheduleFlush();
}
}
export { async };