2016-12-10 4 views
6

Lassen Sie uns sagen, dass ich den folgenden Code bin mit ein paar Versprechungen in Serie laufen:Verzögerungen zwischen Versprechungen in Versprechen Kette

let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function(result) { 
    return mySpecialFunction(item); 
    }) 
}, Promise.resolve()) 

Der Code ruft einfach mySpecialFunction (die ein Versprechen zurückgibt), wartet auf das Versprechen, aufgelöst werden und dann mySpecialFunction erneut aufrufen usw. Die Funktion wird also für jedes Element im Array einmal in der richtigen Reihenfolge aufgerufen.

Wie kann ich sicherstellen, dass zwischen jedem Anruf von mySpecialFunction(item) eine Verzögerung von mindestens 50 Millisekunden besteht?

Es ist wichtig, dass die Versprechen in der richtigen Reihenfolge ausgeführt werden und die Ausführungszeit von mySpecialFunction variiert jedes Mal.

Ich denke, ein synchroner Schlaf würde funktionieren, aber ich plane nicht, diesen Code in einem separaten Thread zu laufen, so würde es störende ui Einfrieren im Browser verursachen.

Ich bin mir nicht sicher, ob setTimer irgendwie dafür verwendet werden könnte. Ich meine, ich kann die Rückgabe eines Versprechens nicht verzögern.

+1

Dies könnte helfen http://bluebirdjs.com/docs/api/promise.delay.html –

+0

Ich habe das schon gesehen, aber ich verwende nicht Bluebird. Ich verwende native Promises. (ECMA6) – Forivin

Antwort

8

Die Antworten sind gut, aber sie warten zu lange, da alle Antworten egal davon warten, ob die tatsächliche Operation mehr als 50ms bereits dauerte.

Sie können Promise.all dafür verwenden.

const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); 
let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function(result) { 
    return Promise.all([delay(50), mySpecialFunction(item)]); 
    }) 
}, Promise.resolve()) 
+1

Beat mich um 37s :-) – Bergi

1

Nachfolgend ein Beispiel dafür, wie man ein Versprechen erreichen könnte, das nicht aber für eine bestimmte Zeitperiode wartet nicht blockiert:

function timedPromise(ms, payload) { 
    return new Promise(function(resolve) { 
     setTimeout(function() { 
      resolve(payload); 
     }, ms); 
    }) 
} 


var time = Date.now(); 

timedPromise(1000) 
    .then(function() { 
     console.log(time - Date.now()); 
     return timedPromise(2000); 
    }).then(function() { 
     console.log(time - Date.now()); 
     return timedPromise(3000); 
    }); 

Also, je nach genau das, was Sie wollen, sollten Sie in der Lage sein, so etwas tun:

let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function(result) { 
    return mySpecialFunction(item); 
    }).then(function(specialResult) { 
    return timedPromise(50, specialResult); 
    }); 
}, Promise.resolve()) 
3

Eine echte und praktische Nutzenfunktion um sich zu haben ist etwas, das ich delay() nennen:

function delay(t, val) { 
    return new Promise(function(resolve) { 
     if (t <= 0) { 
      resolve(val); 
     } else { 
      setTimeout(resolve.bind(null, val), t); 
     } 
    }); 
} 

Dann können Sie es in ein Versprechen Kette wie folgt verwenden:

// delayT is optional (defaults to 0) 
function iterateSerialAsync(array, delayT, fn) { 
    if (!fn) { 
     fn = delayT; 
     delayT = 0; 
    } 
    array.reduce(function(p, item, index) { 
     return p.then(function() { 
      // no delay on first iteration 
      if (index === 0) delayT = 0; 
      return delay(delayT, item).then(fn) 
     }); 
    }, Promise.resolve()); 
} 

:

let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item, index) { 
    return promise.then(function(result) { 
    // no delay on first iteration 
    var delayT = index ? 50 : 0; 
    return delay(delayT, item).then(mySpecialFunction); 
    }) 
}, Promise.resolve()); 

Sie auch ein wenig Nutzenfunktion für das Erledigen der sequentiellen Iteration mit optionaler Verzögerung machen könnte Und dann würden Sie es so verwenden:

iterateSerialAsync(paramerterArr, 50, mySpecialFunction).then(function(finalVal) { 
    // all done here 
}); 
1

Her e Sie gehen: https://jsbin.com/suvasox/edit?html,js,console

let paramerterArr = ['a','b','c','d','e','f'] 
paramerterArr.reduce((p, val) => { 
    return p.then(() => { 
    return new Promise((res) => { 
     setTimeout(() => { res(mySpecialFunction(val)); }, 1000); 
    }); 
    }); 
}, Promise.resolve()); 

p das Ergebnis der p.then sein muss(). Nur so verkettet man die Versprechen.

Beachten Sie, ich habe es nur für die Betonung auf 1000ms Verzögerung geändert.

2

Um eine Verzögerung von mindestens 50ms zu erhalten, verwenden Promise.all:

function delay(t) { 
    return new Promise(function(resolve) { 
    setTimeout(resolve, t); 
    }); 
} 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function() { 
    return Promise.all([ 
     mySpecialFunction(item), 
     delay(50) 
    ]); 
    }); 
}, Promise.resolve()); 
0

da dies eine Voraussetzung für mySpecialFunction zu sein scheint, dass ich es dort umsetzen würde. Damit die Funktion Verzögerungen selbst wenn es weniger als 50 ms nach dem letzten Aufruf aufgerufen wird

const delayBetweenCalls = (delay, fn) => { 
    let lastCall = NaN; 
    return function(/*...arguments*/){ 
     //this and arguments are both forwarded to fn 

     return new Promise(resolve => { 
      let poll =() => { 
       let delta = Date.now() - lastCall; 
       if(delta < delay){ 
        setTimeout(poll, delta - delay); 
       }else{ 
        lastCall = Date.now(); 
        resolve(fn.apply(this, arguments)); 
       } 
      } 
      poll(); 
     }) 
    } 
} 

dann:

const mySpecialFunction = delayBetweenCalls(50, function(some, ...args){ 
    return someValueOrPromise; 
}); 

//and your loop stays the same: 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function(result) { 
     return mySpecialFunction(item); 
    }) 
}, Promise.resolve()) 

so spielt es keine Rolle, wo/wie mySpecialFunction genannt wird, wird es immer eine Verzögerung von mindestens 50 ms, bevor der Code innerhalb des übergebenen Callbacks ausgeführt wird.

Verwandte Themen