2016-10-05 4 views
2

Ich habe diese Funktion:weiter zum nächsten Schritt nur, wenn die Funktion 10 Mal ausgeführt wurde

function setIntervalX(callback, delay, repetitions): Promise<any> { 

    let promises = []; 

    var x = 0; 
    var intervalID = window.setInterval(function() { 
    callback(); 
    if (++x === repetitions) { 
     window.clearInterval(intervalID); 
     promises.push(new Promise((resolve, reject) => {}); 
    } 
    }, delay); 
    return Promise.all(promises); 
} 

Mein Ziel ist es, eine Funktion in Test aufrufen und die nach diesen 10 Anrufe beendet haben, möchte ich erwarten anrufen in meiner Funktion. Das heißt also, dass ich muss warten, bis es zu Ende, wie folgt aus:

setIntervalX(() => { 

    //logic here 

    }, 1000, 10).then(() => { 
        expect(something).toBe(anotherThing); 
        }); 

Ich glaube, dass meine Art und Weise, dies zu tun ist hässlich, und kann bettery erfolgen. Irgendwelche Vorschläge?

+0

ok, ich habe es umformatiert, wirst du jetzt helfen :)? –

+0

Mit Respekt, aber siehe oben. Würden Sie das wirklich "konsistent und lesbar" formatiert nennen? "Callback" ist im ersten Codeblock falsch ausgerichtet, was irreführend ist; dieser erste Block weist auf andere Weise immer noch eine inkonsistente Einrückung auf; und je weniger über den zweiten Codeblock gesagt wird, desto besser. Wenn Sie Ihren Beitrag und Code klarstellen und zeigen, dass Sie sich die Zeit dafür genommen haben, verbessern Sie Ihre Chancen, gute Antworten zu erhalten. –

+0

Wenn dies ein Test ist, warum werden sie mit einem Intervall von 1 Sekunde abgegrenzt, anstatt sie nur hintereinander auszuführen? Es ist auch nicht klar aus Ihrer Frage, ob "Callback" eine Zusage zurückgeben kann, dh effektiv eine asynchrone Operation darstellt, und ob es weniger als eine Sekunde dauert (dh die Tests werden nacheinander ausgeführt) oder mehr (sie werden gleichzeitig ausgeführt) dh parallel). Dies zu klären könnte eine bessere Frage sein. – jib

Antwort

2

Sofern Sie die einzelne Versprechen müssen (man sich nie zuvor verwenden, außer in Promise.all), nur ein einziges Versprechen verwenden:

function setIntervalX(callback, delay, repetitions): Promise<any> { 
    return new Promise(resolve => { 
     let x = 0; 
     let intervalID = window.setInterval(function() { 
      callback(); 
      if (++x === repetitions) { 
       window.clearInterval(intervalID); 
       resolve(); 
      } 
     }, delay); 
    }); 
} 
+0

toll, aber es ist immer noch nicht elegant und könnte besser gemacht werden? –

+0

@ JerzyGruszka: Anders als das Entfernen der unnötigen "Fenster" auf den Timer-Funktionen, bin ich mir nicht sicher, was Sie sonst tun würden. –

+0

@ T.J.Crowder dies kann Fehler nicht korrekt propagieren, wenn callback() eine abgelehnte Versprechen wirft oder zurückgibt. – jib

1

Sie RxJS auch markiert, damit ich eine Rx-Lösung werfen würde. diese

function setIntervalX(callback, delay, repetitions): Observable<any> { 
    //Emit an event every delay 
    return Rx.Observable.interval(delay) 
    //Only accept a certain number of events 
    .take(repetitions) 
    // Process the callback each time 
    .do(() => callback()) 
    // Convert the result into a promise 
    .toPromise(); 
} 

setIntervalX(() => { 
    //logic here 
}, 1000, 10) 
.then(() => {     
    expect(something).toBe(anotherThing); 
}); 
1

Sie wollen eine elegantere Lösung, wie folgt vor:

var wait = ms => new Promise(resolve => setTimeout(resolve, ms)); 
 

 
let setIntervalX = (cb, delay, reps) => 
 
    Promise.all(Array(reps).fill().map((n, i) => wait(delay * (i + 1)).then(cb))); 
 

 
// Demo: 
 

 
let test =() => Promise.resolve().then(() => (console.log("test"), "!")); 
 

 
setIntervalX(test, 1000, 10).then(results => console.log(results.join("")));

ich den Code in Ihrer Frage interpretieren wollen Versprechen der Rückkehr callback s zu unterstützen. Dies unterstützt dies und propagiert auch Fehler korrekt, was mit setInterval schwer zu tun ist.

Die setInterval und setTimeout APIs haben schreckliche Fehler Fahreigenschaften auf ihre eigenen, und sind am besten fest in winzigen Versprechen der Rückkehr Funktionen eingewickelt, nie direkt wieder aufgerufen werden.

Beachten Sie, dass dies für hohe Werte von repetitions nicht besonders effizient ist.

Verwandte Themen