你遇到困难的地方是.then
实际上并没有阻止。它可以帮助您将同步代码转换为异步代码,但它不会为您这样做。让我们首先考虑您尝试重写的同步代码。想象Db.get
是一个返回值而不是承诺的同步函数:
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")
}
};
在这种情况下,当我打电话时someFn
我得到的是一个价值,而不是一个承诺。也就是说整个功能是同步的。
如果我们暂时快进几年并想象我们可以使用 ES6。这将使我们将您的函数重写为:
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")
}
});
看起来很相似,但这次我们有Db.get
返回一个承诺,并且someFn()
也总是会返回一个承诺。这yield
关键字实际上“暂停”当前函数,直到履行承诺。这让它看起来就像同步代码,但实际上是异步的。
回到现在,我们需要弄清楚如何写这个。 a 的第二个参数.then
call 是一个错误处理程序,因此与 ES6 示例完全相同:
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")
});
});
请注意每个返回如何仅从其当前函数范围返回。没有办法强迫它一路跳出来someFn
.
另一个有趣的实验是:
Db.get('id', 'abc')
.then(function () {
console.log('B');
});
console.log('A');
上面的内容总是会记录:
A
B
because .then
不阻止。