可以(应该)JavaScript 承诺用于 co-dependent 功能吗?
Can (should) JavaScript promises be used for co-dependent functions?
Promises 非常适合将某些内容附加到异步调用的 end,而异步调用不需要知道其追随者。 promises 是否可以用于更一般或更复杂的情况,即在异步调用过程中需要回调,如果可以,它能否提供相同级别的分离?
例如,假设您有两个函数 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');
});
});
}
我知道这两个函数可以分别分成两部分并用 promise 串在一起,但这可能会丢失 a1/b1 中重要的 expensive-to-compute 范围变量设置,或者导致冗余代码甚至更难遵循执行顺序。
问题是,是否可以使用 promise 重写这段代码,使 b() 不需要知道 a(),但确实为调用者提供了插入某些东西的机会 before b() 执行完毕?
在回答之前,我稍微修改了您的示例以突出显示执行流程:
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
returns
c
returns
b
returns 并完成执行
a
returns 执行完毕。
稍后,当动画帧可用时,会发生这种情况:
d
被称为
d
同步调用 e
e
呼叫 requestAnimationFrame
- 等等
当然 e
可以访问 b
中定义的变量,由于 JavaScript 闭包,这些变量比原始 b
的执行时间更长。
同样,在 JavaScript 中,我们将 a
视为一个异步操作,一旦 a
启动的所有内容都已完成,它就会结束,但只有两个异步步骤(4 和 11)在其中,所以这两个将从承诺中受益。
现在回答您的问题:在 b 不知道 a 的情况下,promises 能否提供相同的结果和分离?是的,但它不会与您的示例进行公平比较,因为它会在不需要时将您的同步调用增加为异步:
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 returns步在a后面执行,这是一个可以重复的模式。
这个模式好吗?如果不了解更多关于原始用例的信息,很难说。对于异步调用,我还没有遇到没有从 promises 中受益的调用,但是对于同步调用,我不会,因为它会改变执行顺序(除非可能只有一个异常值,而其他所有异常值都是异步的,这有助于提高可读性) .
Promises 非常适合将某些内容附加到异步调用的 end,而异步调用不需要知道其追随者。 promises 是否可以用于更一般或更复杂的情况,即在异步调用过程中需要回调,如果可以,它能否提供相同级别的分离?
例如,假设您有两个函数 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');
});
});
}
我知道这两个函数可以分别分成两部分并用 promise 串在一起,但这可能会丢失 a1/b1 中重要的 expensive-to-compute 范围变量设置,或者导致冗余代码甚至更难遵循执行顺序。
问题是,是否可以使用 promise 重写这段代码,使 b() 不需要知道 a(),但确实为调用者提供了插入某些东西的机会 before b() 执行完毕?
在回答之前,我稍微修改了您的示例以突出显示执行流程:
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
returnsc
returnsb
returns 并完成执行a
returns 执行完毕。
稍后,当动画帧可用时,会发生这种情况:
d
被称为d
同步调用e
e
呼叫requestAnimationFrame
- 等等
当然 e
可以访问 b
中定义的变量,由于 JavaScript 闭包,这些变量比原始 b
的执行时间更长。
同样,在 JavaScript 中,我们将 a
视为一个异步操作,一旦 a
启动的所有内容都已完成,它就会结束,但只有两个异步步骤(4 和 11)在其中,所以这两个将从承诺中受益。
现在回答您的问题:在 b 不知道 a 的情况下,promises 能否提供相同的结果和分离?是的,但它不会与您的示例进行公平比较,因为它会在不需要时将您的同步调用增加为异步:
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 returns步在a后面执行,这是一个可以重复的模式。
这个模式好吗?如果不了解更多关于原始用例的信息,很难说。对于异步调用,我还没有遇到没有从 promises 中受益的调用,但是对于同步调用,我不会,因为它会改变执行顺序(除非可能只有一个异常值,而其他所有异常值都是异步的,这有助于提高可读性) .