Как запустить событие JS, которое зависит от 2 (или более) условий - PullRequest
1 голос
/ 06 июля 2011

Я использую 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
    });
};

Примечание: я принял свой собственный ответ на данный момент, но все еще открыт для более эффективных способов справиться с этим.

Ответы [ 2 ]

1 голос
/ 06 июля 2011

Поскольку некоторые хранилища (веб-хранилище и 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
    };
};
1 голос
/ 06 июля 2011

Я обычно обращаюсь к счетчику, когда выполняю асинхронные операции, которые зависят друг от друга.

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, почти равна нулю.

...