jQuery.Deferredのお勉強にもどうぞ!
フォロー、コメントお待ちしてます
jquery-asyncEach.js
if(jQuery) !function($){
'use strict';
if( typeof $.asyncEach === 'undefined' ){
// setTimeoutとDeferredを使い非同期にする関数
var async = function($callback){
var $dfd = $.Deferred();
setTimeout(function(){
$callback($dfd);
},0);
return $dfd.promise();
};
// $.asyncEachメソッド本体
$.asyncEach = function($array,$callback,$thisArg){
if( typeof $thisArg === 'undefined' ) $thisArg = $array;
//$arrayが大量だった時に$whenを作るのに時間がかかるのでいきなり非同期化
return async(function($dfd){
//$arrayの要素を1個づつ非同期化
var $when = $.map($array,function($value,$index){
return async(function($dfd){
return $callback.call($thisArg,$dfd,$value,$index);
});
});
//$whenが全てresolveするとdone、ひとつでもrejectするとfailする
return $.when.apply($,$when)
.done(function(){
//argumentsを配列に変換して返す
var $_ = [];
$_.push.apply($_,arguments);
return $dfd.resolve($_);
})
.fail(function(){
var $_ = [];
$_.push.apply($_,arguments);
return $dfd.reject($_);
})
;
});
};
}
}(jQuery);
テストコード
!function(){
console.log('最初に表示される');
$.asyncEach([1,2,3,4,5,6,7,8,9,10],function($dfd,$value,$index){
//ここに重い処理(…の、かわりにランダムで待たせてから返す)
var $r = Math.floor( Math.random() * 1050 );
setTimeout(function(){
//どちらかを使って返り値を返す
// $dfd.resolve() = 処理成功
// $dfd.reject() = 処理失敗
return $r <= 1000
? $dfd.resolve($value * 2)
: $dfd.reject($value + 'がキモイ');
},$r);
}).then(//.done,.failでもいい
function($result){
console.log('重い処理が全部終わったら呼ばれる');
console.log($result);
},function($result){
console.log('途中でrejectされたら呼ばれる');
console.log($result);
}
);
console.log('asyncEachは非同期なので2番目に表示される');
}()