2016-01-10 2 views
3

Здравствуйте, я создаю приложение, в котором я использую indexeDB. На основе конфигурации приложения я могу выбрать, следует ли использовать indexeDB из WebWorker или из основного потока пользовательского интерфейса. Соединение из основного потока пользовательского интерфейса всегда выполняется независимо от конфигурации. Однако, исходя из конфигурации, тяжелый подъем выполняется от работника, если он выбран.IndexedDB main thread & WebWorker eventlisteners

Пример импорта прототипа:

Database.prototype.importItem = function(item, callback) { 

    if (this.settings.useWorker) { 

     this.postMessage({ 
      cmd: "importItem", 
      data: item 
     }, callback); 

    } else { 

     var that = this; 
     var transaction = this.db.transaction(this.settings.collection, "readwrite"); 
     var objectStore = transaction.objectStore(this.settings.collection); 
     var request = objectStore.add(item); 

     request.onerror = function(evt) { 
      if (callback && callback instanceof Function) { 
       callback(new ApplicationError("importItem error", evt.target.error), null); 
      } 
     }; 

     request.onsuccess = function(evt) { 
      if (callback && callback instanceof Function) { 
       callback(null, evt.target.result); 
      } 
     }; 

     transaction.oncomplete = function(evt) {}; 

    } 
}; 

Что мне любопытно мысли слушателей событий, которые требуются от индексированной, например:

Database.prototype.connect = function() { 

    if (!this.supported()) { 
     return this.emit("error", new ApplicationError("IndexedDB not supported!")); 
    } 

    var that = this; 
    var openRequest = window.indexedDB.open(this.settings.dbName, this.settings.dbVersion); 

    /** 
    * [onerror description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onerror = function(evt) { 
     that.emit("error", new ApplicationError("openRequest.onerror error", evt.target.error)); 
    }; 

    /** 
    * [onblocked description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onblocked = function(evt) { 
     // If some other tab is loaded with the database, then it needs to be closed 
     // before we can proceed. 
     alert("Please close all other tabs with this site open!"); 
    }; 

    /** 
    * [onsuccess description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onsuccess = function(evt) { 

     that.db = evt.target.result; 

     that.db.onerror = function(evt) { 
      logger.warn("openRequest.onsuccess error", evt.target); 
     }; 

     that.db.onabort = function(evt) { 
      logger.warn("openRequest.onsuccess abort", evt.target); 
     }; 

     that.db.onversionchange = function(evt) { 
      that.db.close(); 
      that.emit("versionchange", new ApplicationError("openRequest.onsuccess version change", evt.target)); 
     }; 

     if (that.settings.useWorker) { 
      that.requestWorker(); 
     } else { 
      that.emit("connect"); 
     } 

    }; 

    /** 
    * [onupgradeneeded description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    openRequest.onupgradeneeded = function(evt) { 

     var stores = {}; 

     that.db = evt.target.result; 

     that.db.onerror = function(evt) { 
      logger.warn("openRequest.onupgradeneeded error", evt.target); 
     }; 

     that.db.onabort = function(evt) { 
      logger.warn("openRequest.onupgradeneeded abort", evt.target); 
     }; 

     that.db.onversionchange = function(evt) { 
      that.db.close(); 
      that.emit("versionchange", new ApplicationError("openRequest.onupgradeneeded version change", evt.target)); 
     }; 

     // Check for the objectStore - collection and delete it if exists 
     if (that.db.objectStoreNames.contains(that.settings.collection)) { 
      that.db.deleteObjectStore(that.settings.collection); 
     } 

     // Create new objectStore 
     stores[that.settings.collection] = that.db.createObjectStore(that.settings.collection, { 
      keyPath: that.settings.indexes[0] 
     }); 

     // Create database indexes 
     that.settings.indexes.forEach(function(index) { 
      stores[that.settings.collection].createIndex(index, index, { 
       unique: false 
      }); 
     }); 

     that.upgraded = true; 
     that.emit("upgrade"); 

    }; 

    /** 
    * [onbeforeunload description] 
    * @param {[type]} evt [description] 
    * @return {[type]}  [description] 
    */ 
    window.onbeforeunload = function(evt) { 
     that.db.close(); 
    }; 

}; 

Поскольку я всегда подключения первого из главный ui, а затем от работника, должен ли я просто слушать события типа «onblocked, versionchange» только в основном потоке пользовательского интерфейса, а не в рабочем? Я полагаю, что это не нужно слушать из обоих потоков?

UPDATE

Я знаю, что это странно, но реализация этой причине я думал об этом, потому что я создаю приложение на самом компьютере, который имеет 3 ГБ оперативной памяти и 2 ядра ... Также у меня есть метод, который выполняет итерацию всех записей в коллекции из моего db. То, что я думал, это передать каждую запись, полученную другим методом для загрузки изображений, а затем, возможно, вызвать обратный вызов ... Это ограничило бы использование памяти, поскольку это было бы сделано в серии, если я не ошибаюсь. Однако я не уверен, что сделка все еще будет жива.

Нижняя линия - вот основная причина, по которой я думал о 2-х подключениях (из-за 1 метода), и мне было интересно, могу ли я избежать двойных прослушивателей событий. Возможно, некоторые из них на 1 нить.

+0

Почему вы даже подключаетесь к обоим потокам, если вы всегда используете indexedDB только из одного потока? –

+0

Поскольку существуют методы, которые не поддерживаются веб-мастером. Например, у меня есть метод, который выполняет итерацию всех элементов в коллекции и передает курсор на обратный вызов, который делает рисование холста, а холст не поддерживается в веб-работниках. – Syd

+0

Да, но для этого вам не требуется индексированное соединение DB в основном потоке - вы все равно можете получить данные в Worker и отправить их в основной поток; затем нарисуйте холст. Вам НЕ нужно подключаться как от Главной нити, так и от Рабочего. То, что вы описали, просто плохой дизайн, или вы описали его неправильно. –

ответ

1

Вы делаете это неправильно. Соединение IndexedDB не должно открываться в обоих потоках. Это делает вашу архитектуру приложения излишне сложной. Данные, полученные из IndexedDB, можно легко обменивать с потоками пользовательского интерфейса через Web workers' messaging channel.

+0

Да, вы правы, я изменил свою реализацию. однако в отношении событий onblocked и т. д. контролируются только в активном потоке (рабочий или основной), и сообщения отправляются пользователю – Syd

+0

@Syd Я не понимаю вашу точку зрения. Не могли бы вы это разъяснить? Почему * события onblocked и т. Д. Контролируются только в активном потоке *, вопрос? – Lewis

+1

События запускаются в определенных экземплярах объектов (например, запросы, транзакции, соединения), которые существуют только в рабочем или оконном контексте и не могут быть переданы. Поэтому, если вы открываете соединение в рабочем месте, вы не можете слушать события из окна, так как вам нечего подключать к прослушивателю событий. –