在 webdriver.io 的 while 循环中链接承诺
Chaining promises in a while loop in webdriver.io
我想通过捕获视口大小的图块来截取整个网页的屏幕截图。快完成了,但我对 promises 还很陌生,我正在寻找正确的方法。
这是我的代码。问题是对 client.execute(...).then(...) 的调用不会在循环迭代之间等待自身。而最后的'end'也不等待前面的'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()
;
在这种情况下使用 promise 的正确方法是什么?
谢谢。
您不能使用 while
链接链接不确定数量的异步操作,因为 while 循环将 运行 立即完成,但您需要在每次异步后做出循环决策执行。
相反,您可以创建一个内部函数 next()
,它 return 是一个承诺并重复调用它,将每个链接到前一个直到完成,并在循环内决定是否将另一个调用链接到 next()
通过 return 在先前的 .then()
处理程序中对其进行处理,或者您可以通过 return 处理常规值(不是承诺)来结束链。
...
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
});
作为参考,如果您在 .then()
处理程序中并且您 return 来自 .then()
处理程序的承诺,那么该承诺将链接到先前的承诺。如果您 return 取而代之的是一个值,那么 promise 链就到此结束,并且该值被 return 编辑为整个链的最终解析值。
因此,在此示例中,由于 next()
return 是一个承诺,您可以从 .then()
处理程序中重复调用 return next();
,这将链接所有屏幕截图一起进入一个顺序链,直到你最终 return 一个值,而不是一个承诺,这将结束链。
我想通过捕获视口大小的图块来截取整个网页的屏幕截图。快完成了,但我对 promises 还很陌生,我正在寻找正确的方法。
这是我的代码。问题是对 client.execute(...).then(...) 的调用不会在循环迭代之间等待自身。而最后的'end'也不等待前面的'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()
;
在这种情况下使用 promise 的正确方法是什么?
谢谢。
您不能使用 while
链接链接不确定数量的异步操作,因为 while 循环将 运行 立即完成,但您需要在每次异步后做出循环决策执行。
相反,您可以创建一个内部函数 next()
,它 return 是一个承诺并重复调用它,将每个链接到前一个直到完成,并在循环内决定是否将另一个调用链接到 next()
通过 return 在先前的 .then()
处理程序中对其进行处理,或者您可以通过 return 处理常规值(不是承诺)来结束链。
...
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
});
作为参考,如果您在 .then()
处理程序中并且您 return 来自 .then()
处理程序的承诺,那么该承诺将链接到先前的承诺。如果您 return 取而代之的是一个值,那么 promise 链就到此结束,并且该值被 return 编辑为整个链的最终解析值。
因此,在此示例中,由于 next()
return 是一个承诺,您可以从 .then()
处理程序中重复调用 return next();
,这将链接所有屏幕截图一起进入一个顺序链,直到你最终 return 一个值,而不是一个承诺,这将结束链。