我正在编写一个基于$ .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承诺(无论是从Web服务还是从缓存读取数据)。以下是我的客户端代码中存储库的用法:
repository.getTasks().done(function (tasks) {
// display list
}).fail(function(err) {
// show error
});
现在我想要的是另一个通过id以相同方式查找任务的函数。所以我需要 findTask 函数来调用 getTasks 函数,然后尝试通过id在列表中查找任务项。我现在的问题是在promise中返回一个任务项。但是find方法现在返回整个列表(基本上它返回了getTasks函数的结果)。但我需要的方式与我下面列出的方式相同:
repository.findTask(765).done(function (task) {
// display task item 765
}).fail(function(err) {
// show error
});
非常感谢。
答案 0 :(得分: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];
}
}
})
}
演示:Fiddle
注意:这种方法的一个问题是,即使未找到该项,也会调用完成的回调。
另一种解决方案是创建自己的延迟类似
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();
}
演示:Fiddle