2

$.getJSON() と HTML5 の sessionStorage をキャッシュとして基本的なリポジトリを作成しています。

初めてデータが要求されたとき、リポジトリは Web サービスからデータを読み取り、それを sessionStorage に格納するため、次回のデータはキャッシュから読み取られます。以下は、Task エンティティを操作するための私のリポジトリのコードです。

Storage.prototype.setObject = function (key, value) { this.setItem(key, JSON.stringify(value)); };
Storage.prototype.getObject = function (key) { return JSON.parse(this.getItem(key)); };

var repository = function () {
    var getTasks = function () {
        if (sessionStorage.getObject("Tasks") {
            return $.Deferred().resolve(sessionStorage.getObject("Tasks")).promise();
        }
        else {
            return $.getJSON("/gettasks").done(function (data) {
                sessionStorage.setObject("Tasks", data);
            }).promise();
        }
    }

    var findTask = function (id) {
        var item;
        return getTasks().done(function (tasks) {
            for(var t in tasks)
                if(tasks[t].id == id)
                    item = tasks[t];
        }).resolve(item);
    }

    return {
        getTasks: function () { return getTasks(); },
        findTask: function (id) { return findTask(id); }
    };
}();

とにかく、 getTasksの戻り値の型はjQuery promise です (データが Web サービスから読み取られるかキャッシュから読み取られるかに関係なく)。クライアントコードでのリポジトリの使用法は次のとおりです。

repository.getTasks().done(function (tasks) {
    // display list
}).fail(function(err) {
    // show error
});

今私が欲しいのは、同じ方法で ID でタスクを見つけるための別の関数です。したがって、 getTasks関数を呼び出すにはfindTask関数が必要であり、ID でリスト内のタスク アイテムを見つけようとします。私の問題は、約束で単一のタスク項目を返すことです。しかし、find メソッドは現在、リスト全体を返しています (基本的には getTasks 関数の結果を返しています)。しかし、私は以下のようにリストを読むのと同じ方法でそれを必要とします:

repository.findTask(765).done(function (task) {
    // display task item 765
}).fail(function(err) {
    // show error
});

どうもありがとう。

4

1 に答える 1

1

deferred.thenを使用してみてください

var findTask = function (id) {
    return getTasks().then(function (tasks) {
        for (var t in tasks) {
            if (tasks[t].id == id) {
                return tasks[t];
            }
        }
    })
}

デモ:フィドル

注: このアプローチの問題点の 1 つは、アイテムが見つからない場合でも、done コールバックが呼び出されることです。

別の解決策は、独自の遅延のようなものを作成することです

var findTask = function (id) {
    var deferred= jQuery.Deferred();
    getTasks().done(function (tasks, status, xhr) {
        for (var t in tasks) {
            if (tasks[t].id == id) {
                deferred.resolveWith(this, [tasks[t]]);
                return;
            }
            deferred.reject(xhr, 'error', 'NOT FOUND');
        }
    }).fail(function(xhr, status, textStatus){
        deferred.reject.apply(deferred, arguments);
    });

    return deferred.promise();
}

デモ:フィドル

于 2013-11-09T11:44:06.793 に答える