forの変数iを非同期処理の関数の引数として渡したい
問題のコード
なんのこっちゃという見出しですが、まずはこちらを見てください。
script.js
tokumei()
.then(function () { // 成功にたどりかない&失敗にもいかない
console.log('成功');
}, function () {
console.log('失敗');
});
function tokumei () {
var paramList = [];
var d = new $.Deferred();
// paramListになにがしかをpushする処理(中略)
for (var i = 0; i < paramList.length; i++) {
ajaxFunc(paramList[i]) // ajax関数の呼び出し
.then(function () {
if (paramList.length === i + 1) d.resolve(); // resolveされない。
}, function () {
d.reject();
});
}
return d.promise();
}
function ajaxFunc(param) {
var d = new $.Deferred();
var url = '/api/nanikanoapi?=' + param;
setTimeout(function () {
$.ajax({
url: url,
dataType: 'jsonp',
cache: false,
timeout: 10000
})
.done(function (data) {
if (parseInt(data['response_code']) !== 400){
d.resolve();
} else {
d.reject();
}
})
.fail(function () {
d.reject();
});
}, 200);
return d.promise();
}
これ、動きません。
// resolveされない
んです。
変数iが意図したように渡せません。
解決策
forの中で即時関数を実行してクロージャーを生成、引数にiを指定して渡してあげればOKでした。
正解のコード
script.js
tokumei(PDS)
.then(function () {
console.log('成功'); // 成功にたどり着く
}, function () {
console.log('失敗');
});
function tokumei () {
var paramList = [];
var d = new $.Deferred();
// paramListになにがしかをpushする処理(中略)
for (var i = 0; i < paramList.length; i++) {
(function (i) { // クロージャー生成
ajaxFunc(paramList[i]) // ajax関数の呼び出し
.then(function () {
if (paramList.length === i + 1) d.resolve(); // resoleveされた!
},function(){
d.reject();
});
})(i);
}
return d.promise();
}
function ajaxFunc(param) {
var d = new $.Deferred();
var url = '/api/nanikanoapi?=' + param;
setTimeout(function () {
$.ajax({
url: url,
dataType: 'jsonp',
cache: false,
timeout: 20000
})
.done(function (data) {
if (parseInt(data['response_code']) !== 400){
d.resolve();
} else {
d.reject();
}
})
.fail(function () {
d.reject();
});
}, 200);
return d.promise();
}
ざっくりした書き方ですが、こんなかんじでいけました!