IndexedDB: избягване на callback-hell

Имам IndexedDB, който локално кешира данни с три свойства a, b и c. a и b заедно образуват съставен ключ, а c е съдържанието, което преследвам.

Сега клиентът получава от сървъра списък с елементи, които искам да покажа. След това клиентът трябва да потърси (a,b) в IndexedDB и да извлече съвпадащото c, след това да хешира c, използвайки sha1 (използвайки Rusha, това вече работи добре).

За тези елементи, където sha1(c_client) не съответства на sha1(c_server), клиентът извлича всички (a,b) двойки от сървъра (използвайки една GET заявка с JSON-сериализиран масив от (a,b)). Сървърът връща актуализираното съдържание на c и след това клиентът съхранява новия c в IndexedDB и след това дава целия масив от обекти на функцията за показване.

Както можете да видите, по-голямата част от логиката абсолютно се нуждае от последователни операции - но IndexedDB е силно асинхронна.

Има ли начин да направя това, което искам по синхронен начин?


person Skynet    schedule 23.01.2014    source източник
comment
Докато основните браузъри не внедрят ES6 генератори, няма начин просто да пишете синхронно. Най-добрият ви залог е да използвате библиотека за контролен поток, за да облекчите болката или да програмирате в async- осведомен надмножество на Javascript, който се компилира във версията за обратно извикване на кода, като това   -  person hugomg    schedule 23.01.2014
comment
По принцип това ще изисква от мен да опаковам целия API на IndexedDB в async.js-wrapper?   -  person Skynet    schedule 23.01.2014
comment
Не, вашият код все още ще взаимодейства с indexdBAPI чрез същите обратни извиквания, както преди. Разликата е, че тези инструменти позволяват на кода ви да бъде малко по-организиран, вместо да имате този пирамида на съдбата модел на вложени обратни извиквания.   -  person hugomg    schedule 23.01.2014


Отговори (2)


Подходът ми към обратните извиквания IndexedDB беше с изпращане на събития, използвайки модел за абониране за публикуване. Можете да кодирате свой собствен манипулатор или да използвате JQuery тригери.

Това, което направих, е да групирам всички логически IndexedDB събития и когато се случи обратното извикване IndexedDB, това ще уведоми издателя какъв вид събитие е настъпило и издателят ще уведоми всички функции, които чакат това събитие.

Примерни събития, които имам, са: създадена база данни, завършено индексиране, стартирана синхронизация, завършена синхронизация... Имам и събития за напредък на синхронизирането, които се използват за уведомяване на потребителя за напредъка (синхронизирам на партиди).

Моделът за публикуване и абониране ми позволи високо ниво на отделяне на кода IndexedDB от кода на потребителския интерфейс и по този начин ми позволи лесно да променя кода на действията на събитието или да добавя повече слушатели към същото събитие. Ако имате нужда от последователна функция, можете да свържете събитията във верига, когато едно приключи, за да задействате, че е готово и следващото може да продължи.

person Deni Spasovski    schedule 24.01.2014
comment
Pubsub моделът е твърде отделен, ще доведе до код за разпространение. Моделът Promise или generator* е за предпочитане за индексиран db api. - person Kyaw Tun; 25.01.2014
comment
Здравейте Kyaw, съгласен съм, че обещаващият модел е по-добър подход за верижно свързване на събития, но в моя случай работи добре с pubsub шаблона, тъй като използвам за свързване на различни логически обекти и нямам дълбоко верижно свързване. - person Deni Spasovski; 27.01.2014

Версията за синхронизиране на API на IndexedDB беше изоставена преди спецификацията да бъде финализирана, така че винаги ще трябва да работите по асинхронен начин.

Също така бях раздразнен от API, така че създадох проста обвивка, наречена db.js, която използва Promises за запитването. Ако имате достатъчно късмет да се насочите само към платформа, която поддържа генератори, можете да ги комбинирате с db.js за направи го по-синхронно.

person Aaron Powell    schedule 29.01.2014