Промисы и jQueryПромисы
Олег Гайдаренко / markelog
Concurrency
Способыпараллельного
исполнения задачТредыПроцессыFibersCoroutineetcиPromise'ы
JS is a singlethreadlanguage
Браузеры имеют только одинтредтак же как и NodeJS
Но при этомВ NodeJS
Worker'ыЧтение/запись сдискаСетевые запросыetc
БраузерыСетевые запросыДекодирование изображенияНекоторые из CSS-transition'овWeb-worker'ыetc
История промисовПридуманы в 1976 годуПервая «имплементация» в MultiLisp'е в 1980-ыхОкончательное сформирование концепции в 1988годуПервая имлементация в E в 1997 году
В ДжаваскриптеСначала в MochaKit – 2005 год
Реализация вдохновлена фреймворком Twister (Python)Dojo – 2006 год
CommonJS предложение – 2010 годИдея популязирована с имплементацией в jQuery c версии 1.5 –
2011 год
Предложения вCommonJS
Promises/AОписана только основная концепция – пайпинг, неизмеямостьстейта, поведение при появлении ошибки и метод «then»Есть так же еще несколько «спек» – B, KISS, DОснованные на той или иной библиотеки для промисовНо все они остались в тени Promise/A предложения
Domenic Denicola
Его участие в истории промисов началось с библиотеки как расширение для библиотеки юнит-тестов
Первое в эту библиотеку, описывала проблему работы вместес jQuery промисамиВпоследствии эта продолжилась в jQuery баг-трекереВ ней обсуждались одна деталь имплементации промисов в jQuery,которая казалось бы не была такой уж важной
chai-as-promised Chai
issue
дискуссия
Сначала никто неслушал
"Your point go from very helpful to laughablyinsane""That's complete non-sense""We do not want to do that"
Но со временем...Доменик становился все более и более вокальнымЕго участие начало проявляться во многих популярных промис-библиотекВроде и И вот год назад поступил в клиентскую MVC-библиотеку Этот пулл имплементировал jQuery-like промисы в Ядро ЭмбераЧто было неприемлимо с точки зрения Доменика, это сподвигло егонаписать известную и во многом поворотную в историиприображения концепции ПромисовПлодом которой является спека
Q when.jsпулл-реквест
Эмбер
статью
Promise/A+
Promise/A+На ней основываются большинство существующих промис-имплементацийОписывает более детальный и ясный процесс резолвинга промисаи работу метода thenГарантированное ассинхронное исполнение и самое важное...
InteroperableОзначает совместимость между любой библиотекойреализовывающих спекуЭто достигается точностью и четкостью формулировокспецификации:
Promise/A библиотеки могли бы быть всегда ассинхронными илииногда ассинхроннымиthen-метод мог иметь progressHandler, а могли и не иметьetc
В NodeJSNodeJS становилась все более и более популярнойТак же как и ассинхронная модель работы с ней становилась всеболее и более раздражающейПромисы же являются элигантным решением выхода из...
Callback Hellfirst(function () { second(function () { third(function () { fourth(function () { iDontKnowHowMuchMoreOfThisICanTake(function () { // Fuck this, i'm going home }); }); }); });});
А с промисамиfirst().then( second ).then( third ).then( fourth ).yeahhh(function() { // Now we talking});
$.when( first, second, third, fourth, loveIt ).then(function() { // This is how we do!});
DOM PromisesСо временем возникло понимание необходимости решения этойпроблемы на уровне языкаЭто нужно было решать и нужно было решать быстроTC39-коммитет довольно медленно и обстоятельно включаетновые идеи в языкПоэтому для того что бы ускорить этот процесс, стандартизацияПромисов на уровне ДОМ'аПосле некоторых метафорфоз эта спека стала являлаться простой
на репозиторий Доменика
началась
ссылкой
APIКак Promise/A+ расширяет Promise/A, так и DOM Promise'ырасширяют Promise/A+i.e. DOM Promise спека является совместимой с Promise/A+Предыдущие спеки не задавали то как должен быть созданПромис-объектПомимо метода then, спека декларирует достаточное API дляработы с ассинхронными задачамиНо при этом предоставляет минималистичное АПИ, последующиерасширения же должны происходить на уровне библиотек
ВендорыЭтого черновика уже было достаточно для разработчиковДжаваскрипт движковВ SpiderMonkey и V8 они включены как примитивы языкаБраузеры же всего лишь эмитируют промисы как ДОМ API, хотятаким он не являлсяПри этом в Chromium'е, не смотря на то что эта спецификацияявляется драфтом, промисы уже включены по-умолчаниюТакая поспешность порадила довольно много ошибок вимплементации
ECMAScript 6Но Промисы должны быть имлементированы на уровне языка!После того как в спеку были внесены дополнительные правки, 20-ого Января 2014 года, новая спецификация была внесена в драфтECMAScript 6Но для того чтобы описание Промисов было достаточно дляимплементации на уровне движка, в язык пришлось внести понятиеTask'ов
Microtasks vs Macrotasks
Синхронные иАссинхронные I/O
Например:fs.readFileSync() и fs.readFile()$.ajax({ async: false }) и $.ajax()
Microtasks queueprocess.nextTick, Object.observe
Macrotasks queueОни же:
«Task Queue» в HTML5Или «Event Queue» вДарте
setTimeout, setIntervalI/OsetImmediate – особый метод, так же работает с очередьюмакротасков, но кладет их на самый верх FIFO стека
А что же jQueryDeferred?
Критика"Promise implementation in jQuery is broken""But just like I should be nice to retarded children, I probably should alsowelcome jQuery promises" @domenicИ довольно большое количество людей в той или иной степенипереиначивающих слова ДоменикаjQuery по-прежнему нарушает все существующие Промис спекиИ будет их нарушать!
TC39jQuery Foundation состоит в TC39И могли бы заблокировать новую ECMAScript ПромисспекуНо мы не хотим быть злодеями в этой истории
Так чем же jQuery имплиментациявызвала такую ненависть?
Ровно четырьмя аспектами
У then метод естьprogressHandler callback
progressHandler опционален в Promise/A, но исключен изPromise/A+
Плюсы/минусыПромис теперь не может иметь транзитивныйстейтНу и ладно, зато АПИ более строг и фокусирован
Успешные/Неудавшиеся Каллбекимогут иметь любое количество
аргументовvar def = $.Deferred();def.promise().then(function() { console.log( arguments.length ); // 7});
def.resolve( 0, 1, 2, 3, 4, 5, 6 );
vsvar def = when.defer();def.promise.then(function() { console.log( arguments.length ); // 1});def.resolve( 0, 1, 2, 3, 4, 5, 6 );
Плюсы/минусыСубъективно это менее удобноЕсли нужно передать несколько аргументов, придется хачить ипередавать один объект с нужными свойствамиНу и ладно, зато промис объект теперь представляет собойрезультат выполнение задачиТак же это более консистентно с try...catch конструкцией
Не гарантирует асинхронноеисполнение
Еще одно Promise/A+ нововведениеvar def = $.Deferred();def.promise().then(function() { console.log( 1 );});
def.resolve();console.log( 2 );// 1 2
vsvar def = vow.defer();def.promise().then(function() { console.log( 1 );});
def.resolve();console.log( 2 );// 2 1
Плюсы/минусыМедленее, намного медленееНо зато гарантия асинхронного выполнения помогает создаватьдетерминированную логику, без опасения что какой-то каллбеквыполнится раньше чем должен был бы
ОптимизацияГодная оптимизация из Vow.js
first().then( second ).then( third ).then( fourth )
Не проглатывает ошибкиvar def = $.Deferred();def.promise().then(function() { throw "Error"}).fail(function( error ) { // Will not be called, // instead error will propagate to the main flow console.log( error );});
vsvar def = Q.defer();def.promise.then(function() { throw "Error";}).catch(function( error ) { console.log( error ); // "Error"});
Плюсы/минусыЕсли отсутствует errorHandler, ошибка никогда не будетпоказана пользователюНо такая парадигма дает возможность всплывать ошибкам поцепочки промисовТогда как в jQuery (если нет try...catch клаузы внутри thenметода) ошибка будет отправлена в основной потокНо эта проблема более релевантна при дебаге, чем для продакта
Что мы собираемсяс этим делать?
Мы не можем изменить сигнатуру then метода, а так жеколичество аргументов в каллбеках, и все из-за обратнойсовместимостиМы скорее всего будем гарантировать асинхронное выполнениекаллбековМы подняли вопрос о возможности проглатывания ошибок в случаеотсутствия каллбека для неудачной резолва
The End
Top Related