如何消除取决于2个(或更多)条件的JS事件

时间:2011-07-05 20:29:37

标签: javascript indexeddb

我正在使用IndexedDBWeb SQLWeb 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
    });
};

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

2 个答案:

答案 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
    };
};
相关问题