我正在使用IndexedDB,Web SQL或Web Storage在客户端上存储一些数据(如果客户端不支持任何存储,则回退到AJAX)。页面加载时我想显示商店中的一些数据。但是当DOM准备就绪时我无法显示数据,因为存储可能没有准备好,当存储准备就绪时我无法显示数据,因为DOM可能没有准备好。
显然我可以实现一些检查由dom和store设置的标志的条件,或者我可以使用超时但是看起来很草率(如果需要满足2个以上的条件,则不能很好地扩展)。是否有一种通常“好”的方式来处理这种情况?我更喜欢跨浏览器解决方案(例如watch
无效)。
情况示例:
// FooServiceFactory decides which storage method to use based on
// what the browser allows and returns a new instance of the
// implementation and starts initializing resources.
var fooService = FooServiceFactory.getInstance();
// DOM is ready
window.onload = function() {
// fooService may not be ready yet depending on whether
// storage has already been setup or if resources need to
// be retrieved from the server. But I don't want this calling
// JS to know about that.
fooService.getAllFoo(request, function(response, status) {
// do something with response
});
};
注意:我现在接受了我自己的答案,但我仍然愿意接受更好的处理方法。
答案 0 :(得分:1)
在做相互依赖的异步操作时,我通常会选择一个计数器。
var running = 0;
function fire(){
running++;
//fire ajax bind callback
}
function callback(data){
//do some stuff for this request
if(--running == 0){
//do special stuff that relies on all requests
}
}
两个请求同时返回并且将if子句评估为true的可能性几乎为零。
答案 1 :(得分:1)
由于某些存储(Web Storage和IndexedDB Synchronous API)不是异步的,因此并不总是需要跟踪它。最好让服务实现自己处理它。
一种方法是让实现队列化调用并在存储准备就绪时执行它们。这对于一些客户来说尤为重要,这些客户会在用户准备好之前让用户“允许”商店,这可能会花费无限的时间。以下是如何处理IndexedDB实现的示例。
var FooServiceIndexedDB = function() {
var db = null;
var queue = [];
var dbRequest = window.indexedDB.open("footle", "All kinds of foo");
var initStore = function() {
// Misc housekeeping goes here...
if (queue.length > 0) {
// Things to do if there are queued functions
for (var i = 0; i < queue.length; i++) {
queue[i](); // Run queued function
}
}
};
dbRequest.onsuccess = function(dbRequestEvent) {
db = dbRequestEvent.target.result;
if (db.getVersion() != "1.0") {
db.setVersion("1.0").onsuccess = function(versionEvent) {
// Create stores/indexes
initStore();
};
} else {
initStore();
}
};
// Public accessor
this.getAllFoo = function(request, callback) {
_getAllFoo(request, callback);
};
// Private accessor
var _getAllFoo = function(request, callback) {
if (db == null) {
// This method was called before the store was ready
queue.push(function() {_getAllFoo(request, callback);});
return;
}
// Proceed getting foo
};
};