2016-03-25 11 views
2

Ich möchte einen Screenshot einer vollständigen Webseite erstellen, indem Sie Kacheln der Ansichtsfenstergröße erfassen. Es ist fast fertig, aber ich bin sehr neu in Versprechungen und ich suche nach dem richtigen Weg.Verkettung verspricht in einer while-Schleife in webdriver.io

Hier ist mein Code. Das Problem ist der Aufruf von client.execute (...). Dann wartet (...) nicht auf sich selbst zwischen Schleifeniterationen. Und das letzte "Ende" wartet nicht auf das vorherige "dann", deshalb ist es auskommentiert.

... 
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() 
    ; 

Was ist der richtige Weg, Versprechen in diesem Fall zu verwenden?

Danke.

Antwort

5

Sie können while nicht verwenden, um eine unbestimmte Anzahl von asynchronen Operationen zu verketten, da die while-Schleife sofort ausgeführt wird, Sie aber die Schleifenentscheidungen nach jeder asynchronen Ausführung treffen müssen.

Stattdessen können Sie eine interne Funktion next() erstellen, die ein Versprechen gibt und es immer wieder aufrufen, die jeweils zum vorherigen Verkettungs bis innerhalb der Schleife durchgeführt und zu entscheiden, ob der Kette einen weiteren Anruf zu next() indem sie sie innerhalb eines früheren .then() Handler zurückkehrt oder Sie können die Kette beenden, indem Sie nur einen regulären Wert (kein Versprechen) zurückgeben.

... 
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 
    }); 

Als Referenz, wenn Sie sich in einem .then() Handler sind und Sie kehren ein Versprechen aus dem .then() Handler, dann wird dieses Versprechen auf die vorherigen Versprechen gekettet. Wenn Sie stattdessen einen Wert zurückgeben, endet die Versprechenskette dort und der Wert wird als endgültiger aufgelöster Wert der gesamten Kette zurückgegeben.

So, in diesem Beispiel, da next() ein Versprechen zurückgibt, können Sie immer wieder return next(); aus dem .then() Handler aufrufen und das wird Kette alle Screenshots zusammen in eine sequentielle Kette, bis schließlich nur noch einen Wert zurückgeben, kein Versprechen und Das wird die Kette beenden.