$.ajax で直列処理を行う

2016年もjQuery を使ってます。

f:id:snowlong:20161117184446g:plain

ふと、以下のようなことがしたくなりました。

  • 可変リストのデータを利用してAjaxjsonを取得したい

  • 非同期ではなく一つの処理が終わったら次の処理を実行するようにして、処理の順番を保証したい

  • 戻ってきたdata を処理してViewに描画したい

でいろいろと悩んだのですが以下のように実装しました。

// number_list は可変リストという想定
var number_list = [
  'number1',
  'number2',
  'number3',
  'number4',
];
var html_data = [];
var number_list_length = number_list.length;

var loadDataRecursive = function(){
  if(!number_list ) {
    return;
  }
  var number =  number_list.shift();
  var url = '//cdn.hogehoge.jp/json/' + number + '.json';

  $.ajax({
    type: 'GET',
    url: url,
    dataType: 'jsonp',
    jsonpCallback: 'callback_' + model_code,
  }).done(function(data) {
    // dataをつかって描画処理する
    html_data.push('<p class="title">' + data.productName + '</p>');
    html_data.push('<p class="title">' + data.productNumber + '</p>');

    // 最後まで処理を行ったらappend する
    if(number === number_list_length) {
      $('#model-list').append(html_data.join(''));
    }
    // 再帰的にコール
    if (number) {
      loadDataRecursive();
    }
  }).fail(function() {
    console.log("loadDataRecursive is failed: " + number );
  });
};
loadDataRecursive();

ポイントは

var number =  number_list.shift();

    if (number) {
      loadDataRecursive();
    }

です。

shift()メソッドは、配列から最初の要素を取り除き、その要素を返します。このメソッドは配列の長さを変えます。
いわゆる破壊的なメソッドです。

返された要素をもとに非同期通信を行い、number_listが空になるまでloadDataRecursive()を実行し再帰的に繰り返します。 loadDataRecursive()自体はひとつのjson しか処理を行いません。
number_listの要素数だけ、処理を繰り返すことで処理の順番が保証されます。

描画処理以下のように行います。 配列にDOMデータをプッシュしておいて最後にそいつを表示したいDOMにappend()します。

    // dataをつかって描画処理する
    html_data.push('<p class="title">' + data.productName + '</p>');
    html_data.push('<p class="title">' + data.productNumber + '</p>');

    // 最後まで処理を行ったらappend する
    if(number === number_list_length) {
      $('#model-list').append(html_data.join(''));
    }

これを実現するために丸一日つぶれました。

JS+Node.jsによるWebクローラー/ネットエージェント開発テクニック