1

我正在使用IndexedDBWeb SQLWeb Storage在客户端上存储一些数据(或者在客户端不支持任何存储的情况下回退到 AJAX)。当页面加载时,我想显示来自商店的一些数据。但是当 DOM 准备好时我无法显示数据,因为商店可能还没有准备好,当商店准备好时我无法显示数据,因为 DOM 可能还没有准备好。

显然,我可以实现一些条件来检查 dom 和 store 设置的标志,或者我可以使用超时,但这似乎很草率(如果需要满足两个以上的条件,则无法很好地扩展)。是否有一种普遍“好”的方法来处理这种情况?我更喜欢跨浏览器的解决方案(例如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
    });
};

注意:我现在接受了自己的答案,但仍然愿意接受更好的处理方式。

4

2 回答 2

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 的可能性几乎为零。

于 2011-07-05T21:00:31.087 回答
1

由于某些存储(Web 存储和 IndexedDB 同步 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
    };
};
于 2011-07-06T14:29:22.813 回答