Quelque chose de similaire à jQuery quand / alors: exécution différée avec pause
-
14-11-2019 - |
Question
Je recherche une solution où je suis en mesure d'exécuter différentes fonctions, mais certaines d'entre elles ont besoin d'un délai d'expiration et toutes les fonctions suivantes doivent attendre jusqu'à ce que la précédente soit terminée. Chaque fonction doit être capable de briser le processus complet.
Maintenant, je pensais pousser toutes les fonctions à une pile et en faire une boucle:
function foo() {
// bar() should wait as long the following is finished:
setTimeout(function(){
if ((new Date()).getSeconds() % 2) {
alert('foo');
// break loop through functions (bar is not called)
}
else {
// start next function (bar is called)
}
}, 1000);
}
function bar() {
setTimeout(function(){
alert('bar')
}, 1000);
}
var functions = new Array('foo', 'bar');
for (var i = 0, length = functions.length; i < length; i++) {
window[functions[i]]();
}
Mais comment inclure l'attente / la pause ?!
Noter: Cela devrait fonctionner avec 2+ fonctions (la quantité de fonctions est modifiable)
Note 2: Je ne veux pas utiliser jQuery.
La solution
Remarque: j'ai mis à jour ma réponse, voir en bas du post.
D'accord, jetons un coup d'œil.
Vous utilisez le window[func]()
Méthode, vous devriez donc pouvoir stocker et utiliser les valeurs de retour de chaque fonction.
function a(){
return "value";
}
var ret_val = window['a']();
alert(ret_val);
Créons une règle de retour:
Si la fonction retourne true
, continuez le flux d'exécution.
Si la fonction retourne false
, briser le flux d'exécution.
function a(){
//Do stuff
return (condition);
}
for(i = 0; i < n; i++){
var bReturn = window['function']();
if(!bReturn) break;
}
Maintenant, mettons-le en pratique.
function a(){
//Do stuff
return ((new Date()).getSeconds() % 2); //Continue?
}
function b(){
//Do stuff
return true; //Continue?
}
function c(){
//Do stuff
return false; //Continue?
}
function d(){
//Do stuff
return true; //Continue?
}
var functions = new Array('a', 'b', 'c', 'd');
for (var i = 0; i < functions.length; i++ ) {
var bReturn = window[functions[i]]();
if(!bReturn) break;
}
Selon lorsque vous exécutez le script, par exemple, une période de temps uniforme ou inégale, elle ne fera que l'exécution de la fonction a
ou exécuter des fonctions a
b
& c
. Entre chaque fonction, vous pouvez faire vos activités normales.
Bien sûr, les conditions varient probablement de chaque fonction individuelle dans votre cas.
Voici un Exemple jsfiddle où vous pouvez le voir en action.
Avec quelques petites modifications, vous pouvez par exemple, faire en sorte que si la fonction a
Renvoie False, il sautera la fonction suivante et continuera à la suivante, ou à celle après cela.
En changeant
for (var i = 0; i < functions.length; i++ ) {
var bReturn = window[functions[i]]();
if(!bReturn) break;
}
Pour ça
for (var i = 0; i < functions.length; i++ ) {
var bReturn = window[functions[i]]();
if(!bReturn) i++;
}
Le fera sauter une fonction, chaque fois qu'une fonction renvoie false.
Tu peux l'essayer ici.
Sur une note latérale, si vous cherchiez une fonction d'attente qui "fait une pause" le script, vous pourriez utiliser Ce morceau de code.
function pausecomp(millis){
var date = new Date();
var curDate = null;
do {
curDate = new Date();
}while(curDate-date < millis);
}
Mise à jour
Après avoir ajusté le code, il fonctionne maintenant avec setTimeout
.
L'idée est que vous avez un point d'entrée, en commençant par la première fonction dans le tableau, et transmettez un paramètre d'index de l'endroit où vous êtes actuellement dans le tableau, puis l'index d'incrément avec un pour exécuter la fonction suivante.
Exemple | Code
function next_function(index){
if(index >= functions.length) return false;
setTimeout(function(){
window[functions[index+1]](index+1);
}, 1000);
}
function a(index){
//Do stuff
if(((new Date()).getSeconds() % 2)) return false; //Stop?
next_function(index);
}
function b(index){
//Do stuff
if(false) return false; //Stop?
next_function(index);
}
function c(index){
//Do stuff
if(true) return false; //Stop?
next_function(index);
}
function d(index){
//Do stuff
if(false) return false; //Stop?
next_function(index);
}
var functions = new Array('a', 'b', 'c', 'd');
//entry point
window[functions[0]](0);
Autres conseils
C'est exactement le scénario promesses résoudre. En particulier, le fait que les promesses puissent être rompues sont parfaites pour votre situation, car une promesse brisée empêche la chaîne de se poursuivre (tout comme une exception lancée dans le code synchrone).
Exemple, en utilisant le Q Bibliothèque Promise discuté dans les diapositives ci-dessus:
function fooAsync() {
return Q.delay(1000).then(function () {
if ((new Date()).getSeconds() % 2) {
alert("foo");
throw new Error("Can't go further!");
}
});
}
function barAsync() {
return Q.delay(1000).then(function () {
alert("bar");
});
}
var functions = [fooAsync, barAsync];
// This code can be more elegant using Array.prototype.reduce, but whatever.
var promiseForAll = Q.resolve();
for (var i = 0; i < functions.length; ++i) {
promiseForAll = promiseForAll.then(functions[i]);
}
// Of course in this case it simplifies to just
// promiseForAll = fooAsync().then(barAsync);
promiseForAll.then(
function () {
alert("done!");
},
function (error) {
alert("someone quit early!");
// and if you care to figure out what they said, inspect error.
}
).end();