ゆるふわエンジニアのブログ

行ったこと、調べたこと等をつらつらと書いていくかもしれません。

Deferredのthen、done、failでハマったこと(jQuery)

本記事では、jQueryのDeferredを使用する際、
then、done、failでハマったことを紹介していきます。

本記事の内容です。

Deferredって何?

本記事で説明すると長くなってしまうので、
下記のページを参照してください。
簡単に説明しますと、「非同期処理を良い感じに行う仕組み」です。
techblog.yahoo.co.jp
qiita.com

何でハマったのか?

以下のコードで処理が思った順番に実行されない。
doneHogeとfailHogeが両方、一気に実行されてしまう。

$(function() {
    $('#button').click(function() {
        $.get({
            url: '何かしらのurl'
        }).done(doneHoge()).fail(failHoge());
    });

    function doneHoge(data, textStatus, jqXHR) {
        alert('Done!');
    }

    function failHoge() {
        alert('Fail...');
    }
});

何が駄目だったのか?

then、done、failは、あくまでも引数の関数を登録するだけなので、
引数で渡す時に"()"を付けてしまうと、
渡している関数が即時実行され登録されない。
上記から、関数の後ろに"()"を付けずに、引数で渡さなければいけない。

修正後のコード

修正コード1は、関数を即時実行させずに情報を渡し登録させるパターン。

修正コード1

$(function() {
    $('#button').click(function() {
        $.get({
            url: '何かしらのurl'
        }).done(doneHoge).fail(failHoge);
    });

    function doneHoge(data, textStatus, jqXHR) {
        alert('Done!');
    }

    function failHoge() {
        alert('Fail...');
    }
});


修正コード2は、関数を即時実行するが、
即時実行した関数から登録する関数を返してあげるパターン。
こちらはコードが長くなるが、細かいことが行える。

修正コード2

$(function() {
    $('#button').click(function() {
        // $.get({
        //     url: '何かしらのurl'
        // }).done(doneHoge).fail(failHoge);
        hoge().done(doneHoge()).fail(failHoge());
    });

    function hoge() {
        var defer = $.Deferred();
        // なにかしらの処理を行う
        if (/* 何かしらの条件 */) {
            // 呼び出し元に処理が成功したと伝える
            defer.resolve();
        } else {
            // 呼び出し元に処理が失敗したと伝える
            defer.reject();
        }
        // promiseを作って返す
        return defer.promise();
    }

    function doneHoge(defer) {
        return function (data, textStatus, jqXHR) {
            alert('Done!');
        }
    }

    function failHoge(defer) {
        return function () {
            alert('Fail...');
        }
    }
});

最後に

コードではthenについて触れませんでしたが、
thenもdoneおよびfailと同じです。