Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for callback before continue for loop

I've a for-loop I'm looping through.

I want to make a custom modal and wait for a response before continue it.

How can I achieve this? I know I've to wait for a callback.

Like this example:

 for(var x in array){             alert(x);             console.log(x);         } 

It does exactly what I want to. But I want to have three buttons. But alert is not part of javascript(? It's in the browser.)

So, do you guys have an idea?

I was thinking about doing something like this:

var run = true; function foo(){     if (run){         setTimeout(foo, 500);     } }  function stop(){     run = false; }  foo(); 

and then wait for a stop which calls on a button click before continue. But is this really good practice?

Or use a lambda function as a parameter to the customAlert and a "global" variable that holds the current position of the array I'm going through and do this with functions. Like: Check if array is still holding keys greater than X. Then do the function again and each time increase the global X.

Thank you lostsource for the code: Oh, I got an idea; I'll simply use lostsource's solution inside an anonymous function, so I don't get global variables. Excellent.

(function(){  })(); 
like image 552
Muqito Avatar asked Jan 18 '13 22:01

Muqito


People also ask

How do you wait inside a for loop?

The Solution—Async/Await Your loop needs to wait for the asynchronous task to complete on each round of the for loop. To make this happen, mark your function asynchronous using the async keyword, and place an await keyword in front of the action you want to wait for.

Is callback a closure?

Callbacks are also closures as the passed function is executed inside other function just as if the callback were defined in the containing function.

How do you wait for a function to finish?

Wait for function to finish using async/await keywords As you already know from the Promise explanation above, you need to chain the call to the function that returns a Promise using then/catch functions. The await keyword allows you to wait until the Promise object is resolved or rejected: await first(); second();

How do you wait for something in JavaScript?

The standard way of creating a delay in JavaScript is to use its setTimeout method. For example: console.log("Hello"); setTimeout(() => { console.log("World!"); }, 5000); This would log “Hello” to the console, then make JavaScript wait 5 seconds, then log “World!”


2 Answers

Assuming this is your array

var list = ['one','two','three']; 

You can try using this loop / callback approach

var x = 0; var loopArray = function(arr) {     customAlert(arr[x],function(){         // set x to next item         x++;          // any more items in array? continue loop         if(x < arr.length) {             loopArray(arr);            }     });  }  function customAlert(msg,callback) {     // code to show your custom alert     // in this case its just a console log     console.log(msg);      // do callback when ready     callback(); } 

Usage:

// start 'loop' loopArray(list); 

JSFiddle here: http://jsfiddle.net/D9AXp/

like image 57
lostsource Avatar answered Sep 30 '22 15:09

lostsource


MaggiQall, I know you have an answer but I have a flexible solution that may be of interest to you or maybe to someone else.

The solution depends on jQuery (1.7+) and jQuery UI's dialog, but is implemented as a custom method of the Array prototype, not as a jQuery plugin.

Here's the Array method :

Array.prototype.runDialogSequence = function(dialogCallback, startIndex, endIndex){     startIndex = Math.max(0, startIndex || 0);     endIndex = Math.min(this.length - 1, endIndex || this.length - 1);     var sequenceIndex = 0,         arr = this,         dfrd = $.Deferred().resolve(startIndex);     function makeCloseFn(seqData){         return function(event, ui){             if(seqData.continue_) { seqData.dfrd.resolve(seqData.arrayIndex+1, seqData); } //continue dialog sequence             else { seqData.dfrd.reject(seqData.arrayIndex, seqData); } //break dialog sequence         }     }     $.each(this, function(i){         if(i < startIndex || i > endIndex) { return true; }//continue         dfrd = dfrd.then(function(arrayIndex){             var seqData = {                 dfrd: $.Deferred(),                 arrayIndex: arrayIndex,                 sequenceIndex: ++sequenceIndex,                 length: 1 + endIndex - startIndex,                 item: arr[arrayIndex],                 continue_: false             };             dialogCallback(seqData).on("dialogclose", makeCloseFn(seqData));             return seqData.dfrd.promise();         });     });     return dfrd.promise(); } 

Array.runDialogSequence() relies on :

  • A dialog template in the document's body, fit to be populated with text/values.
  • an array of similar items (typically javascript objects) containing the data required to populate the dialog, in sequence.
  • passing, as the first argument, a correctly constructed "openDialog" function.

Here's a sample "openDialog" function with explanatory comments :

function openDialog(seqData){     /*     seqData is an object with the following properties:         dfrd: A Deferred object associated with the current dialog. Normally resolved by Array.runDialogSequence() to run through the sequence or rejected to break it, but can be resolved/rejected here to force the dialog sequence to continue/break. If resolved, then pass (seqData.arrayIndex+1, seqData), or custom values. If rejected, typically pass (seqData.arrayIndex, seqData).         arrayIndex: The current array index.         sequenceIndex: The current index within the sequence. Normally the same as arrayIndex but Differs when a non-zero startIndex is specified.         length: The full length of the dialog sequence.         item: The current item from the array.         continue_: (false) Set to true to allow the sequence to continue.     */     var item = seqData.item;     var $d = $("#d");     $d.dialog({         title: 'Dialog (' + seqData.sequenceIndex + ' of ' + seqData.length + ')',         modal: true,         buttons: {             "Continue": function(){                 seqData.continue_ = true;//set to true before closing to go to next dialog.                 $(this).dialog("close");             },             "Cancel": function(){                 $(this).dialog('close');//closing with seqData.continue_ set to its default value false will break the dialog sequence.             }         }     }).find("#message").text(item);//Typically you will do a lot more here to populate the dialog with item data.     return $d;//openDialog() must return a dialog container, jQuery-wrapped. } 

Array.runDialogSequence() returns a jQuery promise, allowing custom actions to be performed when the dialog sequence completes (done function) or is broken in mid-sequence (fail function).

Here are a couple of sample calls :

//Simplest possible $("#myButton1").click(function(){     myArray.runDialogSequence(openDialog); });  //Call with custom startIndex and endIndex, and chanined `.then()` to provide custom actions on break/completion. $("#myButton2").click(function(){     myArray.runDialogSequence(openDialog, 1, 3).then(function(i, seqData){         alert('All dialogs complete - last item = "' + seqData.item + '"');     }, function(i, seqData){         alert('Dialog sequence was broken at item ' + i + ' "' + seqData.item + '"');     }); }); 

DEMO

This is as close to a generalized solution as my imagination allows.

like image 24
Beetroot-Beetroot Avatar answered Sep 30 '22 15:09

Beetroot-Beetroot