promise then return a specified promise gives the following code snippet:
function get(url) {
return new Promise(function(resolve, reject) {
var req =
Chain Promises
You can chain your promises if you want them sequential:
get('a.json').then(function(a) {
return get('b.json');
}).then(function(b){
return get('c.json');
}).then(function(c) {
// all done here
}), function(err) {
// error here
});
Or in ES7, you can use async/await
like this:
async function someFunction() {
let a = await get('a.json');
let b = await get('b.json');
// do something with a and b here
return something;
}
someFunction().then(result => {
// all done here
}).catch(err => {
// error here
});
Run Promises in Parallel
If you want them loaded in parallel, you can use Promise.all()
:
Promise.all([get('a.json'), get('b.json'), get('c.json')]).then(function(results) {
// all done with results here
}, function(err) {
// error here
});
Sequence Using .reduce()
Or, if you use the same code to process each result, you can load them sequentially using the reduce()
design pattern:
['a.json', 'b.json', 'c.json'].reduce(function(p, item) {
return p.then(function(){
// process item here
});
}, Promise.resolve()).then(function(result) {
// all done here
}, function(err) {
// error here
});
Sequence Using Bluebird's .map()
Or, if using the Bluebird promise library, it has Promise.map()
which is very useful for parallel operations on an array
Promise.map(['a.json', 'b.json', 'c.json'], function(item) {
// do some operation on item and return data or a promise
return something;
}).then(function(results) {
// all done
}, function(err) {
// error here
});
get(x).get(y).get(z)
WorkExtending the Promise
I was intrigued by the get(x).get(y).get(z)
question using promises. I conjured up a way to do that in this working snippet:
function get(url) {
function pget(u) {
var p = this.then(function (result) {
log(result);
return get(u);
});
p.get = pget;
return p;
}
var p = new Promise(function (resolve, reject) {
setTimeout(function() {
resolve(url);
}, 500);
});
p.get = pget;
return p;
}
get('a.json').get('b.json').get('c.json').then(function(result) {
log(result);
log("done");
}, function(err) {
log("err");
});
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
This is a bit of a hack. I think the standards body is working on a more official way to extend a promise like this that will work in more cases than this will. But, I tried it in Chrome, Firefox and IE with Bluebird and this particular usage works in all three. The challenge with this method is that every .then()
creates a new promise and, by default, it will not have your .get()
method on it. We get away with it here because of the way it is used, but you would have to be careful exactly how you use this.
Chaining Our Own Object
Here's a bit different way to do the get(x).get(y).get(z)
syntax. It requires a blank .get()
at the end to tell you it want to stop the chain and get access to the final promise. The advantage of this scheme is that it doesn't mess with the promise object in any way.
function delay(url) {
return new Promise(function (resolve, reject) {
setTimeout(function() {
log(url);
resolve(url);
}, 500);
});
}
function get(url) {
function pget(u) {
if (!u) {
return this.promise;
} else {
return {promise: this.promise.then(function() {
return delay(u);
}), get: pget}
}
}
return {promise: delay(url), get: pget};
}
// note the empty .get() right before the .then()
// the empty .get() at the end is required in this scheme
get('a.json').get('b.json').get('c.json').get().then(function(result) {
log("done");
}, function(err) {
log("err");
});
function log(x) {
var div = document.createElement("div");
div.innerHTML = x;
document.body.appendChild(div);
}
You can join promises , in that case you have to return next promise from success callback
get('story.json').then(function(response) {
console.log("Success!", response);
return get('b.json');
}, function(error) {
console.error("Failed!", error);
}).then(function(res){
// response for b
});