icon 2017/05/11 Ajax非同期処理を実装
JavaScriptでAPIからデータ取得・処理する際、ネスト地獄で複雑なコードになりがち。
かと言って、AngularやReactなどのフレームワークを使うと勉強コスト、スパゲティー設計など本末転倒な結果になりやすい。

フレームワークの最大のデメリットは、

中で何が行われているか?ソースを解読しないとわからない


と言うことで、こみいった実装をせずシンプルに実装してみる。

(1) APIリクエストの配列設定
(2) Ajax処理の抽象化
(3) 並列処理の抽象化
(4) コールバック処理の考慮
    $(document).on('click', '.action-api', function() {
        //API設定(抽象化する必要あり)
        var requests = [
            {
                url: 'https://xxxx/api/user',
                params: {'user_id': 394},
                callback: callbackUser
            },
            {
                url: 'https://xxxx/api/order',
                params: {'user_id': 394, 'item_id': 31},
                callback: callbackApplication
            },
        ];

        //並列処理実行
        parallelAjax(requests, doneCallback);

        //各APIリクエストのコールバック
        function callbackUser(results) {
            console.log(results);
        }
        function callbackApplication(results) {
            console.log(results);
        }
        //並列処理完了後のコールバック
        function doneCallback(results) {
            console.log(results);
        }
    });

var requestAjax = function(values){
    var $ajax = $.ajax(values);
    var defer = new $.Deferred();
    $ajax.done(function(data, status, $ajax){
        defer.resolveWith(this, arguments);
    });
    $ajax.fail(function(data, status, $ajax){
        defer.resolveWith(this, arguments);
    });
    return $.extend({}, $ajax, defer.promise());
};

function parallelAjax(requests, callback) {
    var results = [];
    $.each (requests, function(index, value) {
        var $ajax = requestAjax({url: value.url, data: value.params}).done(function(res, status) {
            if (value.callback) {
                value.callback(res);
            }
        });
        results.push($ajax);
    });
    $.when.apply(null, results).done(function(){
        if (callback) callback(results);
    });
    $.when.apply(null, results).fail(function(){
    });
}

APIリクエストの配列設定


並列処理は後々ループで実行ため、オブジェクト配列で設定しておく。
差し当たり以下の項目で設定
・URL
・URLパラメータ
・API処理後のコールバック
(その他、POST/GETやデータ型なども設定できると良い?)
        var requests = [
            {
                url: 'https://xxxx/api/user',
                params: {'user_id': 394},
                callback: callbackUser
            },
            {
                url: 'https://xxxx/api/application',
                params: {'user_id': 394},
                callback: callbackApplication
            },
        ];
こうすることで、callbackを別モデル、ファイルなどに分離して記述できるかと。
実用レベルだと、APIリクエスト設定も動的に抽象化が必要ですが。。。

Ajax処理の一般化


並列処理をする際「jQuery.Deferred」を利用
ざっとした流れは、
(1) Deferredオブジェクトを作成
(2) Ajaxリクエスト
(3) Ajax処理後返り値を Deferred.resolveWith() でコールバック

詳しくは、
「爆速でわかるjQuery.Deferred超入門」
「結局jQuery.Deferredの何が嬉しいのか分からない、という人向けの小話」を参照
var requestAjax = function(values) {
    var $ajax = $.ajax(values);
    var defer = new $.Deferred();
    $ajax.done(function(data, status, $ajax) {
        defer.resolveWith(this, arguments);
    });
    $ajax.fail(function(data, status, $ajax) {
        defer.resolveWith(this, arguments);
    });
    return $.extend({}, $ajax, defer.promise());
};

並列処理の一般化


(1) 配列化したリクエストをループで処理
(2) Ajax実行
(3) APIリクエストで設定したコールバックを実行
(3) $.whenで並列処理完了後の処理
function parallelAjax(requests, callback) {
    var results = [];
    $.each (requests, function(index, value) {
        var $ajax = requestAjax({url: value.url, data: value.params}).done(function(res, status) {
            if (value.callback) {
                value.callback(res);
            }
        });
        results.push($ajax);
    });
    $.when.apply(null, results).done(function(){
        if (callback) callback(results);
    });
    $.when.apply(null, results).fail(function(){
    });
}

このサイトについて

HTML5 & CSS3化しつつあるので、現在IEには対応してません。
できれば、Google Chromeやら Apple SafariのWebKit系をお勧めします。

DBからプログラムまで一応全て自作なので、バグってたらすいません。
実験でFlash版(Flex版)を先に作りましたが、ちょっと停止してます。

プロフィール

新宿近辺でSE & プログラマーしてます。
Webアプリの開発・設計とか、最近はiPhoneとか奮闘してます。
デザインはさっぱりです。

音楽は、昔からCubase打ち込み人間で、そっちの方が経歴は長いですが、最近はやる暇がないです。。。

今は、Gon's Privates ってバンドのキーボードやってます。
単発的に、なんちゃってジャズ系のライブもやってます。

名古屋生まれなのでドラゴンズ好きです。

Info && SNS

Gmail

 yohei.yoshikawa@gmail.com

Twitter

 http://twitter.com/yoo_yoo_yoo

あんまつぶやきませんが、一応技術系メインで使ってます。情報交換はこちらへ

FaceBook

 http://www.facebook.com/#!/profile.php?id=1439130626

海外の知り合いがいないので閑散としてます。

mixi

 http://mixi.jp/show_profile.pl?id=230072

音楽仲間とかはこっちメインでやってます。興味があればこちらへ