从异步/等待块中提取部分代码到单独的函数中

时间:2018-06-29 19:58:23

标签: javascript node.js asynchronous ecmascript-6

我有一个异步匿名自调用功能。函数前的单词“ async”表示该函数将始终返回promise。如果代码返回了代码,则JavaScript会自动将其包装为具有该值的已解决的Promise。

此异步允许我们使用“等待”。关键字await使JavaScript等待该承诺完成并返回其结果。因此,函数执行会“暂停”并在诺言达成后恢复。这不会花费任何CPU资源,因为引擎可以同时执行其他工作:执行其他脚本,处理事件等。

(async () => {
    await page.goto('test.com', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
    await page.evaluate((user, pass) => {
      document.querySelector('#user').setAttribute('value', user);
    }, user, pass)
    await page.click('button[type=submit].btn-primary');


    for(var i = 0; i < 10; i++){
        try { 
            await page.goto('test.com/second', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
        } catch(e) {
                await page.goto('test.com', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
                await page.evaluate((user, pass) => {
                    document.querySelector('#user').setAttribute('value', user);
                }, user, pass)
                await page.click('button[type=submit].btn-primary');
        } 

        // more stuff not relevant here
    }    

})();

但是正如您在上面看到的,我有重复的代码。我想将重复的代码提取到一个单独的函数中。像这样:

(async () => {

    logIn()

    for(var i = 0; i < 10; i++){
        try { 
            await page.goto('test.com/second', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
        } catch(e) {
            logIn()
        } 

        // more stuff not relevant here
    }    

})();


function logIn(){
                await page.goto('test.com', { waituntil: ['load', 'domcontentloaded', 'networkidle0'] });
                await page.evaluate((user, pass) => {
                    document.querySelector('#user').setAttribute('value', user);
                }, user, pass)
                await page.click('button[type=submit].btn-primary');
}

但是,这将不起作用,因为await仅在aysnc内部起作用。现在,一个想法是像这样在登录调用之前放置等待:

await logIn()            

这是问题。在该logIn函数内部,我故意使用await 3次,因为我需要在下一条语句之前解决一条语句。

我该如何实现?使用async / await并使用我的登录功能?

2 个答案:

答案 0 :(得分:0)

也将logIn函数用作异步函数:

async function logIn() {...}

然后,当您调用它时,await用于它:

await logIn();

像这样:

async function logIn() {
  await page.goto('test.com', {
    waituntil: ['load', 'domcontentloaded', 'networkidle0']
  });
  await page.evaluate((user, pass) => {
    document.querySelector('#user').setAttribute('value', user);
  }, user, pass)
  await page.click('button[type=submit].btn-primary');
}

(async() => {
  await logIn();

  for (var i = 0; i < 10; i++) {
    try {
      await page.goto('test.com/second', {
        waituntil: ['load', 'domcontentloaded', 'networkidle0']
      });
    } catch (e) {
      logIn()
    }

    // more stuff not relevant here
  }
})();

More on async functions

答案 1 :(得分:0)

上述解决方案还意味着,调用login的函数以及调用该函数的函数等也都需要保持异步,直到代码库的顶部。

本质上,在任何地方使用async意味着您的所有函数必须是异步的,并且必须使用await来调用所有函数。

我希望我们可以用await / async包装执行运算符,这样我们就不必将其散布到整个应用程序中。

我希望有人能对此进行真正的纠正,因为我没有找到不涉及使所有功能异步并在等待时调用它们的解决方案。

如果您愿意,请随时通过rodney.barbati@gmail.com向我发送电子邮件。我会很感激的。