Chaining 2 Asynchronous Calls (promise API) To Run Serially
Solution 1:
The place where your having difficulty is that .then
doesn't actually block. It helps you convert synchronous code into asynchronous code, but it doesn't do so for you. Lets start by considering the synchronous code you are trying to re-write. Imagine Db.get
was a synchronous function that returned a value, rather than a promise:
var someFn = function (id){
try {
var d = Db.get(id, "abc");
console.log("At 1");
var d = Db.get(d.id, "def");
console.log("At 2")
return d;
} catch (ex) {
console.log("At 3")
}
};
In this case, when I call someFn
I get a value, not a promise. That is to say the entire function is synchronous.
If we temporarily fast forward a few years and imagine we could use ES6. That would let us re-write your function as:
var someFn = $q.async(function* (id){
try {
var d = yield Db.get(id, "abc");
console.log("At 1");
var d = yield Db.get(d.id, "def");
console.log("At 2")
return d;
} catch (ex) {
console.log("At 3")
}
});
That looks very similar, but this time we have Db.get
returning a promise, and someFn()
will also always return a promise. The yield
keyword actually "pauses" the current function until the promise is fulfilled. This lets it look just like the synchronous code, but it's actually asynchronous.
Rewind to the present, and we need to work out how to write this. The second argument of a .then
call is an error handler, so the exact equivalent to the ES6 example would be:
var someFn = function (id){
return Db.get(id, "abc")
.then(function (d) {
console.log("At 1");
return Db.get(d.id, "def");
})
.then(function (d) {
console.log("At 2");
return d;
})
.then(null, function (ex) {
console.log("At 3")
});
});
Note how each return is only returning from its current function scope. There's no way to force it to jump all the way out of someFn
.
Another interesting experiment to do is:
Db.get('id', 'abc')
.then(function () {
console.log('B');
});
console.log('A');
The above will always log:
A
B
because .then
doesn't block.
Solution 2:
I was thinking then would block till it get response from the promise
No. Promises in JS are no transparent, blocking futures, but just a pattern to chain callbacks. The promise is returned before the callback is executed - and At 3
is logged after .then
returns, but before the callback executed. And if you return
in the callback, it doesn't really matter to the outer someFn
.
You rather would use something like
var someFn = function(id){
return Db.get(id, "abc")
.then(function (d) {
console.log("At 1")
return Db.get(d.id, "def");
})
.then(function (d) {
console.log("At 2")
return d
}, function (e) {
//error
});
}
someFn().then(function(d) {
console.log("At 3")
});
Post a Comment for "Chaining 2 Asynchronous Calls (promise API) To Run Serially"