开发者

How to Fire JS Event that Depends on 2 (or more) Conditions

I am using IndexedDB, Web SQL or Web Storage to store some data on the client (or fallback to AJAX in the event the client doesn't support any storage). When the page loads I want to display some data from the store. But I can't display the data when the DOM is ready because the store may not be ready and I can't display the data when the store is ready because the DOM might not be ready.

Obviously I could implement some conditional that checks flags set by the dom and store or I could use a timeout but that seems sloppy (and wouldn't scale well if more than 2 conditions needed to be met). Is there a generally "good" way to handle this situation? I would prefer a cross-browser solution (E.g. watch won't work).

Example of the situation:

/开发者_JAVA技巧/ 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
    });
};

Note: I accepted my own answer for now but am still open to better ways of handling this.


I usually go for a counter when doing asynchronous stuff that relies on each other.

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
  }
}

The possibility of two requests coming back the same time and both evaluating the if-clause to true is almost zero.


Since some storage (Web Storage and the IndexedDB Synchronous API) are not asynchronous, there won't always be a need to keep track of this. It would be best to have the service implementation handle it by itself.

One way would be to have the implementation queue up calls and execute them when the store is ready. This would be especially important with some clients which will make the user "allow" the store before it is ready, which could take an indefinite amount of time. Here's an example of how the IndexedDB implementation could be handled.

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
    };
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜