Promise非常适合将某些内容附加到异步调用的 end ,而异步调用不需要知道其关注者。可以承诺在更常见或复杂的情况下使用,在异步调用中需要回调,如果是这样,它可以提供相同级别的分离吗?
例如,假设你有两个功能a& b执行顺序从a转移到b并返回两次。
使用回调:
function a() {
console.log('a1');
b(function(b2) {
requestAnimationFrame(function() {
console.log('a2');
b2();
});
});
}
function b(a2) {
console.log('b1');
a2(function() {
requestAnimationFrame(function() {
console.log('b2');
});
});
}
我知道这两个函数可以分成两部分并与promises结合在一起,但这可能会丢失在a1 / b1中设置的重要的昂贵计算范围变量,或导致冗余代码甚至更难遵循执行顺序。
问题是,是否可以使用promises重写此代码,使得b()不需要了解a(),但确实为调用者提供了在 b()完成执行?
答案 0 :(得分:2)
在回答之前,我稍微修改了您的示例以突出显示执行流程:
function a() {
console.log('a1');
var c = function(b2) {
var d = function() {
console.log('a2');
b2();
});
requestAnimationFrame(d);
}
b(c);
}
function b(a2) {
console.log('b1');
var e = function() {
var f = function() {
console.log('b2');
});
requestAnimationFrame(f);
}
a2(e);
}
这是相同的代码,除了我已经命名了四个匿名函数c
,d
,e
和f
,因为我想参考它们。
这是执行的顺序:
a
被称为a
同步拨打b
b
同步拨打c
c
调用requestAnimationFrame
(异步API)requestAnimationFrame
返回c
返回b
返回并执行a
返回并完成执行。稍后,当动画帧可用时,会发生这种情况:
d
被称为d
同步拨打e
e
来电requestAnimationFrame
当然,e
可以访问b
中定义的变量,这些变量比原始b
的执行更长,这要归功于JavaScript闭包。
同样,在JavaScript中,我们将a
视为异步操作,一旦所有a
启动完成就结束,但是其中只有两个异步步骤(4和11),所以那两个将受益于承诺。
现在回答你的问题:承诺可以提供相同的结果和分离,而不知道一个?是的,但它不能与您的示例进行公平的比较,因为它会在您的同步调用不需要时将其同步为异步:
function a() {
console.log('a1');
var b2;
b().then(function(result) {
b2 = result;
return new Promise(function(r) { requestAnimationFrame(r); })
}).then(function() {
console.log('a2');
return b2();
}).catch(function(e) {
console.log(e.message); // error-handling
});
}
function b() {
console.log('b1');
return Promise.resolve(function() {
return new Promise(function(r) {
requestAnimationFrame(r);
}).then(function() {
console.log('b2');
});
});
}
这里的技巧是b返回稍后在a中执行的步骤,这是一个可以重复的模式。
这是一个好模式吗?很难说在不了解原始用例的情况下。对于异步调用,我还没有遇到一个没有从承诺中受益的调用,但对于同步调用我不会,因为它会改变执行顺序(除非可能只有一个异常值,所有其余的是异步的,它有助于提高可读性。)