有没有可能调用jquery .each方法异步?

时间:2013-07-17 09:34:36

标签: javascript jquery asynchronous each

好的,我有这个小脚本。

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');
});

这是一种虚拟复选框功能 - 它添加了某个类和属性。一切正常。问题只在于请求的数量,类和属性只在函数执行所有元素的服务时添加,所以如果我有300个需要相当长的时间,是否有机会异步调用此方法每个元素?谢谢你的帮助。

2 个答案:

答案 0 :(得分:2)

不,每个方法都不能异步,因为它是同步的,就像for循环一样:它从第一个元素开始,然后是第二个元素......直到最后一个元素。

答案 1 :(得分:1)

是的,你可以!

虽然每个方法都不是异步的,但您可以使用IIFE(立即调用的函数表达式)或promises异步处理内部内容。检查Promises的代码片段。

基本上,您可以在每个循环迭代中实例化Promise(或IIFE)。 如果你需要一个计算值来检查每个循环中的代码块,Promise和Promise.all会让你更容易,而不是处理IIFE回调。

如果您不需要在Promises中处理已解析的值,请使用IIEF或“free”Promises,而不将它们放入要使用Promise.all进行排序和检查的数组中。

PS:Promise需要最新的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>