简体   繁体   English

在webdriver.io中的while循环中链接诺言

[英]Chaining promises in a while loop in webdriver.io

I want to take a screenshot of a full webpage by capturing tiles of the viewport size. 我想通过捕获视口大小的图块来拍摄完整网页的屏幕截图。 It's almost done, but I'm very new to promises and I'm looking for the correct way to do. 它已经差不多完成了,但是我对诺言很陌生,我正在寻找正确的方法。

Here is my code. 这是我的代码。 The problem is the call to client.execute(...).then(...) does not wait for itself between loop iterations. 问题是调用client.execute(...)。then(...)不会在循环迭代之间等待自身。 And the final 'end' neither waits for the previous 'then', that's why it's commented out. 最后的“结尾”都不等待前面的“ then”,这就是为什么将其注释掉的原因。

...
var client = webdriverio.remote(options);
...
client    
  ...
  .then(function() {

    var yTile = 0;
    var heightCaptured = 0;

    while(heightCaptured < documentSize.height) {
      var tileFile  = 'screenshot-' + yTile + '.png';

      client
      .execute(function(heightCaptured) {
        window.scrollTo(0, heightCaptured);
      }, heightCaptured)
      .then(function() {
        console.log('captured: ' + tileFile);
        client.saveScreenshot('./' + tileFile);

        return client;
      });

      heightCaptured += viewportSize.height;
      yTile++;
    }

  })
  //.client.end()
  ;

What is the correct way to use promises in this case? 在这种情况下使用诺言的正确方法是什么?

Thanks. 谢谢。

You can't use a while look to chain an indeterminate number of async operations because the while loop will run to completion immediately, but you need the loop decisions to be made after each async execution. 您不能使用while外观来链接不确定数量的异步操作,因为while循环将立即运行到完成,但是您需要在每次异步执行之后做出循环决策。

Instead, you can create an internal function next() that returns a promise and call it repeatedly, chaining each to the previous until done and deciding within the loop whether to chain another call to next() by returning it inside a prior .then() handler or you can end the chain by just returning a regular value (not a promise). 相反,您可以创建一个内部函数next() ,该函数返回一个promise并反复调用它,将其链接到前一个,直到完成为止,并在循环内确定是否将另一个调用链接到next()是将其返回到.then()处理程序,也可以通过返回常规值(而不是诺言)来结束链。

...
var client = webdriverio.remote(options);
...
client
    ...
    .then(function () {
        var yTile = 0;
        var heightCaptured = 0;

        function next() {
            if (heightCaptured < documentSize.height) {
                var tileFile = 'screenshot-' + yTile + '.png';

                // return promise to chain it automatically to prior promise
                return client.execute(function (heightCaptured) {
                    window.scrollTo(0, heightCaptured);
                }, heightCaptured).then(function () {
                    console.log('captured: ' + tileFile);

                    // increment state variables
                    heightCaptured += viewportSize.height;
                    yTile++;

                    // return this promise to so it is also chained properly
                    // when this is done, call next again in the .then() handler
                    return client.saveScreenshot('./' + tileFile).then(next);
                });

            } else {
                // Done now, end the promise chain by returning a final value
                // Might also consider returning yTile so the caller knows
                // how many screen shots were saved
                return client;
            }
        }
        // start the loop
        return next();
    }).then(function () {
        // done here
    }, function (err) {
        // error here
    });

As a reference, if you are inside a .then() handler and you return a promise from the .then() handler, then that promise gets chained onto the previous promise. 作为参考,如果您位于.then()处理程序中,并且从.then()处理程序返回一个诺言,则该诺言将链接到先前的诺言。 If you return a value instead, then the promise chain ends there and the value is returned as the final resolved value of the whole chain. 如果您返回一个值,则承诺链到此结束,并且该值作为整个链的最终解析值返回。

So, in this example, since next() returns a promise, you can repeatedly call return next(); 因此,在此示例中,由于next()返回一个promise,因此您可以重复调用return next(); from within the .then() handler and that will chain all your screenshots together into one sequential chain until you finally just return a value, not a promise and that will end the chain. .then()处理程序内部,它将所有屏幕快照链接到一个顺序链中,直到您最终仅返回一个值(而不是promise),并且该链结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM