基于可变数组顺序执行异步方法

Sequentially execute asynchronous methods based on a variable array

我有很多答案。

var answers = ['Yes', 'No', 'Yes']; 

我必须在问题按顺序弹出的网络测验中输入这些答案。我使用 selenium 驱动程序感知问题。

我使用以下方法输入答案。

var answerQuestion = function(driver, answer) {
    var defer = q.defer();

    var elementXPath = "//*[contains(@class, 'quizAnswer’)]";
    var delay = 2000;

    return driver.waintUntilVisible(elementXPath, delay).sendKeys(answer);
};

现在我想对 answers 数组中的每个答案按顺序执行上述方法,因为在回答当前问题之前不会显示下一个问题。

一个简单的 foreach 循环在这里失败了。

function submitAnswers(driver) {
    answers.forEach(function(answer) {
        answerQuestion(driver, answer);
    });
}

那么如何基于可变数组顺序执行异步方法呢

起初answerQuestion应该是有希望的:

function answerQuestion(driver, answer) {
 var elementXPath = "//*[contains(@class, 'quizAnswer’)]";
 var delay = 2000;

 return driver.waintUntilVisible(elementXPath, delay).sendKeys(answer);
}

那就很简单了:

function submitAnswers(driver, position = 0) {
    if(position >= answers.length) return;

    return answerQuestion(answers[position]).then(function() {
      return submitAnswers(driver, position + 1);
    });
 }

或者如果你可以使用 async / await:

async function submitAnswers(driver, answers) {
  for(const answer of answers)
     await answerQuestion(answer);
 }

由于 selenium 函数 returns 承诺,您将必须依次解决。

对于你的案例,下面的内容应该可以发挥作用。

var answerQuestion = function(driver, answer) {
    return function() {
       var defer = q.defer();
       var elementXPath = "//*[contains(@class, 'quizAnswer’)]";
       var delay = 2000;
    return driver.waintUntilVisible(elementXPath,delay).sendKeys(answer);
};

function submitAnswers(driver) {
    return answers.reduce((previous, answer) => {
                return previous.then(answerQuestion(driver, answer);
            }, Promise.resolve());
}

我终于想到了一个办法。感谢 Dave Ceddia

var answers = ['Yes', 'No', 'Yes'];

var answerQuestion = function(driver, answer) {
    var elementXPath = "//*[contains(@class, 'quizAnswer’)]";
    return driver.waintUntilVisible(elementXPath, delay).sendKeys(answer);
};

function submitAnswers(driver) {

    var chain = q.when();

    answers.forEach(function(answer) {
        chain = chain.then(function() {
            return answerQuestion(driver, answer);
        });
    });
}