我在Rasbperry pi上使用nodejs来控制其硬件引脚。 我完全假设代码如:
for (..) {
executeAsyncCode(..)
}
function executeAsyncCode() {
doAsync1().then(doAsync2()).then(doAsync3())...
}
最终将以executeAsyncCode
的每次执行与其他执行完全分离的方式执行,这意味着两个异步执行不会同时运行。但实时验证和使用显示不同。我遇到执行doAsync1(..)
一个接一个地调用executeAsyncCode
函数的两次执行,并在此期间做了很多混乱。
对于我的使用它显然是一个问题,因为硬件不能并行使用,并且在许多情况下我可能想要执行代码并依赖于不需要锁的事实。 如何限制这些代码不能一起执行?有没有办法知道事件循环将如何执行代码?
答案 0 :(得分:1)
所有代码将在事件循环开始下一个上下文之前完成执行。这意味着在执行任何异步回调之前,循环将始终执行完成。例如:
for ( var i = 0; i < 100000; i++ ) {
console.log( 'Hi!' );
setTimeout( function ( ) { console.log( 'foo' ); }, 0 );
}
// Some synchronous operation that takes a long time
console.log( 'bar' );
确定性地输出&#39;嗨!&#39; 100000次后跟'bar'
然后由于脚本中没有其他内容,事件循环有机会运行其他消息,最后'foo'
输出100000次。
如果你想在开始下一个承诺链之前等待第一个承诺链完成,你应该从executeAsyncCode
返回一个承诺,以便你可以在完成时启动下一个:
var previousPromise = Promise.resolve();
for (..) {
previousPromise = previousPromise.then( executeAsyncCode );
}
function executeAsyncCode() {
return doAsync1().then(doAsync2).then(doAsync3)...
}
答案 1 :(得分:0)
要等待所有异步代码完成再次运行它们之前必须执行.then()
内的下一轮。既然你已经在使用promises,你只需要返回链:
function executeAsyncCode() {
return doAsync1().then(doAsync2).then(doAsync3)...
}
然后executeAsyncCode()
本身可以继续.then()
:
executeAsyncCode()
.then(function(){
console.log('finished');
});
所以,两个循环是:
executeAsyncCode()
.then(executeAsyncCode);
五个循环将是:
executeAsyncCode()
.then(executeAsyncCode)
.then(executeAsyncCode)
.then(executeAsyncCode)
.then(executeAsyncCode)
.then(executeAsyncCode);
要进行无限循环,您可以使用javascript动画师和游戏程序员使用的旧的setTimeout样式循环技巧。这是一个无限循环:
function executeAsyncCode() {
doAsync1()
.then(doAsync2)
.then(doAsync3)
.then(executeAsyncCode);
}
可替换地:
function executeAsyncCode() {
doAsync1()
.then(doAsync2)
.then(doAsync3)
.then(function(){
executeAsyncCode();
});
}
第二种语法允许我们编写条件循环:
function executeAsyncCode() {
doAsync1()
.then(doAsync2)
.then(doAsync3)
.then(function(){
if (we_should_loop()) {
executeAsyncCode();
}
});
}
我们也可以构造我们的代码,以便我们可以将循环条件作为参数传递。这是一个简单的倒计时循环:
function executeAsyncCode(count) {
doAsync1()
.then(doAsync2)
.then(doAsync3)
.then(function(){
count--;
if (count) {
executeAsyncCode(count);
}
});
}
所以我们可以这样称呼它:
executeAsyncCode(5); // runs 5 loops
这模拟了一个简单的for循环:
function executeAsyncCode(start, end) {
doAsync1()
.then(doAsync2)
.then(doAsync3)
.then(function(){
start--;
if (start < end) {
executeAsyncCode(start,end);
}
});
}
executeAsyncCode(0, 20); // loops 20 times
这试图模仿for循环的大部分功能:
function executeAsyncCode(x, checkfunction, incrementfunction) {
if (checkfunction(x)) {
doAsync1()
.then(doAsync2)
.then(doAsync3)
.then(function(){
executeAsyncCode(incrementfunction(x));
});
}
}
所以你可以把它称为for循环:
// loops 10 times like a for loop:
executeAsyncCode(0, function(i){return i<10}, function(i){return i++});