4

Ok, i have this little script.

var parent_li = $('ul.list').find('li');
parent_li.each(function(){
    var dmy_checkb = $(this).find('.dmy_checkb'),
        true_inpt = $(this).find('input');
    dmy_checkb.trigger('click');
    true_inpt.attr('checked','checked');
});

This is some kind of dummy checkbox function - it adds a certain class and attribute. Everything works fine. The problem is only in the number of requests, class and attribute are added only when the function is executed services to all elements, so if i have them 300 takes quite a long time, is there a chance for an asynchronous call this method separately for each of the elements? Thx for help.

isherwood
  • 58,414
  • 16
  • 114
  • 157
Lukas
  • 7,384
  • 20
  • 72
  • 127
  • 2
    No, you cannot do that with `.each`. You have to use `setTimeout` and process each element (or set of elements) step by step. Have a look at this question about native `.forEach`: http://stackoverflow.com/q/5050265/218196. – Felix Kling Jul 17 '13 at 09:38
  • 1
    By asynchronously you mean multithreading? – Aurelio De Rosa Jul 17 '13 at 09:38
  • @FelixKling thx for help, `setTimeout` could be helpful, BR – Lukas Jul 17 '13 at 09:59

3 Answers3

2

No, each method can't be asynchronous because it was made to be synchronous, to work like a for loop : it proceeds begining by the first element, then the second... until the last.

Lucas Willems
  • 6,673
  • 4
  • 28
  • 45
1

Yes you can!

Although the each method is not asynchronous you can process the content inside asynchronously, either with IIFE (immediately-invoked function expression) or promises. Check the snippet of code for Promises.

Basically, you can instantiate a Promise (or a IIFE) inside each loop iteration. If you need a computed value to be inspected as a result of your block of code inside the each loop, Promise and Promise.all makes your like easier instead of handling IIFE callbacks.

If you do not need to handle resolved values in Promises, either use IIEF or "free" Promises without placing them into an array to be ordered and inspected with Promise.all.

PS:Promise requires latest JS.

var ulList = $('ul.list');
var btn = $('#btn');
var timeoutOption = $('#useTimeout');

btn.on('click', function(){
  processAsync(timeoutOption.is(':checked'));
});

for(var i = 300; i > 0; i--){
  ulList.append(
    $('<li>').text(i).append(
      $('<div class="dmy_checkb">').on('click', function(){
          $(this).addClass('clicked');
        }),
      $('<input type="checkbox">')
    )
  );
}



function processAsync(_timputOption){
  
  console.log('processAsync called', _timputOption); 

  var parent_li = $('ul.list').find('li');
  
  var clickedPromises = [];
  
  parent_li.each(function(){
  
      var dmy_checkb = $(this).find('.dmy_checkb');
      var true_inpt = $(this).find('input');
          
      
      clickedPromises.push(
        new Promise(function(resolve, reject){
            
            var randomTimeout = 0;

            if(_timputOption){
              randomTimeout = Math.floor(Math.random() * 3) + .2;
            }
            //this timeout is only to prove that processing is async
            
            setTimeout(function(){

              dmy_checkb.trigger('click');
              true_inpt.attr('checked','checked');

              resolve(true_inpt.attr('checked'));
            }, randomTimeout*1000);

        })
      
      );
      
  });
  
  
  //this is called immediatly after the each loop... before all promises are done to show you that your code will continue immediately without waiting for each Promise to finish their work.
  ulList.addClass("orange");
  
  //Promise.all runs after all the array of promises finished its computation
  Promise.all(clickedPromises).then(function(values){
    //called after all promises have been resolved. You can inspect each result in the order has they have been produced 
      //console.log(values);
  });
  

}
ul.list{
  position:absolute;
  top:0;
  bottom:0;
  margin:20px;
  margin-bottom:10%;
  display:inline-block;
  border:1px solid blue;
  overflow:auto;
}

ul.list > li{
  padding:5px;
}

ul.list.orange{
  background-color:orange;
}

#actionBox{
  position:absolute;
  top:0;
  left:0;
  left:100px;
  
  margin:20px;
}

.dmy_checkb{
  border:1px solid lightgray;
  border-radius:4px;
  background-color:lightblue;
  width:16px;
  height:16px;
}
.dmy_checkb.clicked{
  background-color:blue;

}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<ul class="list"></ul>

<div id="actionBox">
  <label for="useTimeout">use timout</label>
  <input type="checkbox" checked name="useTimeout" id="useTimeout">
  <button id="btn">process async</button>
</div>
MFAL
  • 1,090
  • 13
  • 19
-1

Check out the async library for Node. You can use async.each. https://caolan.github.io/async/docs.html

Adrienne
  • 2,540
  • 1
  • 29
  • 39