Labs

<< 最初 < 前ページ 次ページ > 最後 >>
JavaScript のトピック一覧 条件クリア
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(){
    });
}
icon 2016/03/31 form内データ取得
form.submit()でなく、AjaxなどでPOSTするにはform内データを取得する必要があるが、
タグ毎に処理が異なる。
(もっと合理的な書き方はあるかと思うが・・・)

サンプル


サンプル


  <form id="form">
    <h1>result(JSON)</h1>
    <div id="result"></div>

    <h1>form</h1>
    <h2>title</h2>
    <input type="text" name="title" value="">

    <h2>select</h2>
    <select name="status">
      <option value="1">select1</option>
      <option value="2">select2</option>
      <option value="3">select3</option>
      <option value="4">select4</option>
    </select>

    <h2>radio</h2>
    <input type="radio" name="active" value="true">radio1
    <input type="radio" name="active" value="false">radio2

    <h2>checkbox</h2>
    <label for="reason_1"><input id="reason_1" type="checkbox" value="1" name="reason">check1</label>
    <label for="reason_2"><input id="reason_2" type="checkbox" value="2" name="reason">check2</label>
    <label for="reason_3"><input id="reason_3" type="checkbox" value="3" name="reason">check3</label>

    <h2>textarea</h2>
    <textarea id="note" name="note" rows="10" cols="50"></textarea>

    <div>
      <a class="action-update" href="#">UPDATE</a>
    </div>
  </form>

</select>

<input type="radio" name="active" value="true">
<input type="radio" name="active" value="false">

<label for="reason_1"><input id="reason_1" type="checkbox" value="1" name="reason">選択1</label>
<label for="reason_2"><input id="reason_1" type="checkbox" value="2" name="reason">選択2</label>
<label for="reason_3"><input id="reason_1" type="checkbox" value="3" name="reason">選択3</label>

<textarea id="note" name="waste[note]" rows="10" cols=""></textarea>
</form>

input


var posts = {};
$('#form input').each(function() {
    var type = $(this).attr('type');
    var name = $(this).attr('name');
    if (name) {
        if (type == 'checkbox') {
            //TODO 重複
            posts[name] = checkValues(name);
        } else if (type == 'radio') {
            var checked = $(this).prop('checked');
            if (checked)  {
                posts[name] = $(this).val();
            }
        } else {
            posts[name] = $(this).val();
        }
    }
});

function checkValues(name) {
    var column = '[name="' + name + '"]:checked';
    var checks = [];
    $(column).each(function() {
        var checked = $(this).prop('checked');
        if (checked) {
            checks.push($(this).val());
        }
    });
    return checks;
}
厄介なのが「checkbox」でチェックボックスの状態をスキャンしないといけない。
上記サンプルは、checkboxの数だけ無駄に処理してしまっている。

inputタグ毎に明示的にid指定すれば対応は簡単だが、コーディングが冗長的
(場合によってはその方が良い?)
改善策としては、ビジネスロジックやルールをjavascript側で作るのが良さそう。

select


var posts = {};
$('#form select option:selected').each(function() {
    var name = $(this).parent().attr('name');
    if (name) posts[name] = $(this).val();
});

textarea


var posts = {};
$('#form textarea').each(function() {
    var name = $(this).attr('name');
    if (name) {
       posts[name] = $(this).val();
    }
});
icon 2015/05/13 [jQuery] DateTimePickerで日付選択
日付(カレンダー)のJSプラグインは種類はあれど時刻付きは少ない。
jQueryプラグインの「DateTimePicker」は時刻にも対応している。

jQuery Date and Time picker

サンプル


DatetimePickerサンプル

ソース


$(function() {
    var params = {format: 'Y-m-d H:i', lang: 'ja'};
    $('#from_at').datetimepicker(params);
    $('#to_at').datetimepicker(params);
});

<input type="text" id="from_at" class="input-medium" name="from_at" value="">
<input type="text" id="to_at" class="input-medium" name="to_at" value="">
<< 最初 < 前ページ 次ページ > 最後 >>

このサイトについて

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

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