如何做一个;至于;Javascript中异步条件的循环?

如何做一个;至于;Javascript中异步条件的循环?,javascript,asynchronous,ecmascript-6,synchronous,Javascript,Asynchronous,Ecmascript 6,Synchronous,我有这个功能: waitForFreeAccnt.prototype.isMemberFree = function () { var self = this; self.api.getMemberInfo(function () { var accType = self.api.connect.accountType; console.log(accType); if (accType === 'FREE') {

我有这个功能:

waitForFreeAccnt.prototype.isMemberFree = function () {
    var self = this;

    self.api.getMemberInfo(function () {
        var accType = self.api.connect.accountType;
        console.log(accType);
        if (accType === 'FREE') {
            console.log('it is free');
            return true;
        } else {
            console.log('it is not free');
            return false;
        }
    });
};
我想等待,直到帐户是免费的长达10秒,类似的东西:

var test = function () {
    for (var start = 1; start < 10; start++) {
        var result = self.isMemberFree();
        console.log(result);
        if (result) {
            break;
        } else {
            self.api.pause(1000);
            console.log('waiting');
        }
    }
};
var测试=函数(){
对于(var start=1;start<10;start++){
var result=self.isMemberFree();
控制台日志(结果);
如果(结果){
打破
}否则{
self.api.pause(1000);
console.log('waiting');
}
}
};
但它不起作用,因为
self.api.getMemberInfo
是异步调用。这对于Javascript来说是非常令人沮丧的。任何其他语言都很容易做到。在继续循环之前,如何强制for循环等待
self.isMemberFree()
完成执行


还需要注意的是,这不是在浏览器执行中,所以我不关心挂起的任何东西。

我今天没有工作笔记本电脑,因为今天是星期天,我在Supreme上编写这段代码。如果语法有点错误,请道歉

为了解决您的问题,我建议将isMemberFree()更改为接受回调函数。这是因为isMemberFree是异步的,您需要一种在完成工作后报告结果的方法

然后将测试函数更改为使用setTimeout API等待一秒钟。 将isMemberFree()的函数调用包装在嵌套函数中并递归调用,这样您就可以对异步调用进行同步控制

请看编码示例:

waitForFreeAccnt.prototype.isMemberFree = function (done) {
    var self = this;

    self.api.getMemberInfo(function () {
        var accType = self.api.connect.accountType;
        console.log(accType);
        if (accType === 'FREE') {
            console.log('it is free');
            return done(null, true);
        } else {
            console.log('it is not free');
            return done(null, false);
        }
    });
};


var test = function () {

    var testMembership = function(waitAttempt, isFree) {
        if (isFree) { 
            return; 
        }
        else if (waitAttempt > 10) {
            // wait exceeded, do something.
            return;
        }
        setTimeout(function() {
            self.isMemberFree(function(err, isFree) {
                testMembership(waitAttempt+=1, isFree);
            });
        }, /*total milliseconds in 1sec=*/1000);
    }

    testMembership(/*WaitAttempts=*/0, /*isFree=*/false);
};

上面的代码所做的是,可能已经对成员的帐户执行了一些操作,现在调用了test函数。因此它等待1秒,然后调用isMemberFree函数,这种情况会递归发生,直到isMemberFree()返回true或超过10秒的等待时间。

我今天没有工作笔记本电脑,因为今天是星期天,我正在sublime上编写此代码。如果语法有点错误,请道歉

为了解决您的问题,我建议将isMemberFree()更改为接受回调函数。这是因为isMemberFree是异步的,您需要一种在完成工作后报告结果的方法

然后将测试函数更改为使用setTimeout API等待一秒钟。 将isMemberFree()的函数调用包装在嵌套函数中并递归调用,这样您就可以对异步调用进行同步控制

请看编码示例:

waitForFreeAccnt.prototype.isMemberFree = function (done) {
    var self = this;

    self.api.getMemberInfo(function () {
        var accType = self.api.connect.accountType;
        console.log(accType);
        if (accType === 'FREE') {
            console.log('it is free');
            return done(null, true);
        } else {
            console.log('it is not free');
            return done(null, false);
        }
    });
};


var test = function () {

    var testMembership = function(waitAttempt, isFree) {
        if (isFree) { 
            return; 
        }
        else if (waitAttempt > 10) {
            // wait exceeded, do something.
            return;
        }
        setTimeout(function() {
            self.isMemberFree(function(err, isFree) {
                testMembership(waitAttempt+=1, isFree);
            });
        }, /*total milliseconds in 1sec=*/1000);
    }

    testMembership(/*WaitAttempts=*/0, /*isFree=*/false);
};

上面的代码所做的是,可能已经对成员的帐户执行了一些操作,现在调用了test函数。因此它会等待1秒,然后调用isMemberFree函数,这种情况会递归发生,直到isMemberFree()返回true或超过10秒的等待时间。

处理异步代码时,需要使用回调。也就是说,如果您想按顺序执行
a()
b()
,但
a()
异步执行某些操作,那么您需要从
a()
内部调用
b()
,一旦
a()
产生结果。所以不是:

a();  // does something asynchronously
b();  // tries to use a()'s result but it isn't available yet
。。。而是

a(b); // pass b to a() and a() will call it when ready

function a(callback) {
  triggerAsyncFunction(function(result) {
    if (result === something)
      callback("a just finished");
  });
}
请注意,
a()
并没有按名称引用
b()
,它只是调用作为参数传入的任何函数

因此,将其应用到您的代码中,可能类似于:

waitForFreeAccnt.prototype.isMemberFree = function (cbf) {
    var self = this;
    self.api.getMemberInfo(function () {
        cbf(self.api.connect.accountType === 'FREE');
    });
};
waitForFreeAccnt.prototype.testMemberXTimes = function(maxAttempts, callback) {
  var attempts = 0;
  var self = this;
  (function attempt() {
    self.isMemberFree(function(free) {
      if (free)
        callback(true);
      else if (++attempts < maxAttempts)
        setTimeout(attempt, 1000);
      else
        callback(false);
    });
  )();
};
this.testMemberXTimes(10, function(isFree) {
  // the next part of your code here, or called from here
  // because at this point we know we've tested up to
  // ten times and isFree tells us the result
});
waitForFreeAccnt.prototype.isMemberFree=函数(cbf){
var self=这个;
self.api.getMemberInfo(函数(){
cbf(self.api.connect.accountType==='FREE');
});
};
waitForFreeAccnt.prototype.testMemberXTimes=函数(maxAttempts,回调){
var=0;
var self=这个;
(函数尝试(){
self.isMemberFree(函数(免费){
如果(免费)
回调(true);
else if(++尝试次数<最大尝试次数)
设置超时(尝试次数,1000);
其他的
回调(假);
});
)();
};
this.testMemberXTimes(10,函数(isFree){
//代码的下一部分在这里,或者从这里调用
//因为在这一点上,我们知道我们已经测试了
//十次,isFree告诉我们结果
});
请注意,我编写
getMemberInfo()
的方法基本上与您的方法相同,但它不是返回布尔值,而是调用回调函数并传递与您返回的布尔值相同的布尔值。(我删除了
console.log()
以缩短代码。)


还要注意的是,您可以将上述内容结构化为使用承诺,但最终结果将是相同的。

在处理异步代码时,您需要使用回调。也就是说,如果您想按顺序执行
a()
b()
,但
a()
执行异步操作,则需要调用
b()
a()
一次
a()
有一个结果。所以不是:

a();  // does something asynchronously
b();  // tries to use a()'s result but it isn't available yet
…但是

a(b); // pass b to a() and a() will call it when ready

function a(callback) {
  triggerAsyncFunction(function(result) {
    if (result === something)
      callback("a just finished");
  });
}
请注意,
a()
并没有按名称引用
b()
,它只是调用作为参数传入的任何函数

因此,将其应用到您的代码中,可能类似于:

waitForFreeAccnt.prototype.isMemberFree = function (cbf) {
    var self = this;
    self.api.getMemberInfo(function () {
        cbf(self.api.connect.accountType === 'FREE');
    });
};
waitForFreeAccnt.prototype.testMemberXTimes = function(maxAttempts, callback) {
  var attempts = 0;
  var self = this;
  (function attempt() {
    self.isMemberFree(function(free) {
      if (free)
        callback(true);
      else if (++attempts < maxAttempts)
        setTimeout(attempt, 1000);
      else
        callback(false);
    });
  )();
};
this.testMemberXTimes(10, function(isFree) {
  // the next part of your code here, or called from here
  // because at this point we know we've tested up to
  // ten times and isFree tells us the result
});
waitForFreeAccnt.prototype.isMemberFree=函数(cbf){
var self=这个;
self.api.getMemberInfo(函数(){
cbf(self.api.connect.accountType==='FREE');
});
};
waitForFreeAccnt.prototype.testMemberXTimes=函数(maxAttempts,回调){
var=0;
var self=这个;
(函数尝试(){
self.isMemberFree(函数(免费){
如果(免费)
回调(true);
else if(++尝试次数<最大尝试次数)
设置超时(尝试次数,1000);
其他的
回调(假);
});
)();
};
this.testMemberXTimes(10,函数(isFree){
//代码的下一部分在这里,或者从这里调用
//因为在这一点上,我们知道我们已经测试了
//十次,isFree告诉我们结果
});
请注意,我编写的
getMemberInfo()
基本上与您的编写方法相同,但它不是返回布尔值,而是调用回调函数并传递相同的布尔值
result.then(function(res) {
  console.log(res); // 15
});

// or, use an async function again:
var main = async function() {
  console.log(await res); // 15
};
main();