Comments 46
Меня насторожило использование promise-ext-settled — он добавляет своё свойство «allSettled» в нативный Promise конструктор. Так и до Prototype.js недалеко.
0
Array.prototype.concat.apply([], Array.prototype.slice.call(arguments));
Автору не плохо бы самому на собеседование сходить. За подобное использование arguments стоит бить по рукам, тк из-за этого функция никогда не будет оптимизирована в v8.
Для этого в ES6 придумали spread оператор:
function foo(...args) {
console.log(args);
}
+1
Видимо у Вас перманентное желание бить всех по рукам :)
Если Вы присмотритесь, то увидите, что я не использую ES6(2015) синтаксис.
И не использую я его сознательно, чтобы не привлекать библиоетеки типа babel и не увеличивать итоговый размер скрипта
Если Вы присмотритесь, то увидите, что я не использую ES6(2015) синтаксис.
И не использую я его сознательно, чтобы не привлекать библиоетеки типа babel и не увеличивать итоговый размер скрипта
-3
А безымянные функции используются, чтобы отладку упростить?
Ну прям ужасно увеличивает
var ImagePreloader = function(fallbackImage, onProgress) { }
не привлекать библиоетеки типа babel и не увеличивать итоговый размер скрипта
Ну прям ужасно увеличивает
0
Не совсем понятны Ваши претензии. Если считаете, что Вам есть что добавить к коду — милости прошу pull request. На то он и github. Это всяко лучше и продуктивнее саркастически высказываний ;)
+4
Да и не безымянная это функция. Это Function Expression. Если внутри нее возникнет исключение, то в stack trace будет имя функции, в которой возникло исключение.
0
Es6 умеет определять имя функции в var someName = function expression.
Es5 в данном случае будет содержать имя переменной, которой была присвоена функция
Es5 в данном случае будет содержать имя переменной, которой была присвоена функция
+1
Последний хром:
var foo = function() {}
undefined
foo.name
""
-1
Если трансформировать этот код через babel, который поддерживает практически все последние нововведения в язык, то всё будет работать именно так, как я описал ;)
0
Собственно, проблема то в чём?
Докопались до какой-то ерунды. Даа foo.name будет пустым, но в чём трагедия то? Может ещё от => откажемся? Отладка неименованных анонимок уже давно перестала быть чем-то невыносимым.
скриншот
Докопались до какой-то ерунды. Даа foo.name будет пустым, но в чём трагедия то? Может ещё от => откажемся? Отладка неименованных анонимок уже давно перестала быть чем-то невыносимым.
+2
Ради экономии сотни байт вы теряете в читаемости и производительности? Странная экономия на спичках.
В прочем вполне можно обойтись и без babel, самостоятельно приведя аргументы к массиву.
В прочем вполне можно обойтись и без babel, самостоятельно приведя аргументы к массиву.
function foo() {
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
console.log(args);
}
+1
Да само-собой, можно как угодно, но притензия у комментатора была в том, что я не использую spread(которого нет в es5)
-1
Да само-собой, можно как угодно, но притензия у комментатора была в том, что я не использую spread. Но я не использую здесь es6 ;)
-1
Вы пишете «странная экономия на спичках», а затем постите 4 строчную конвертацию arguments в array. Где логика? К тому же Array.prototype.slice.call это уже давно классика.
Устроили целый тред из-за какой-то субъективной глупости.
Давайте ещё найдём у автора for(…; …; i ++); и устром тред про то, что ++ i будет быстрее ;)
теряете … в производительностиДаёшь asm.js в каждый метод? :)
Устроили целый тред из-за какой-то субъективной глупости.
Давайте ещё найдём у автора for(…; …; i ++); и устром тред про то, что ++ i будет быстрее ;)
+3
Нет. Я автору предложил использовать ES6 по полной, автор отказался, я показал альтернативный метод.
Продолжайте себя в этом уверять и не изучать изменения в языке.
К тому же Array.prototype.slice.call это уже давно классика.
Продолжайте себя в этом уверять и не изучать изменения в языке.
-1
Продолжайте себя в этом уверять и не изучать изменения в языке.Я использую и ES6 и ES7. А до ES6 использовал node-fibers. Не делайте скоропостижных выводов. И не беритесь учить окружающих, не понимая сути. Ваша экономия на arguments по большей части неуместна. Воевать вот с этим имеет смысл только в высоко-нагруженных местах.
+1
И да, забыл упомянуть: смысл именно такого concat'а в том, чтобы можно было передавать обычные значения и значения в миссиве в перемешку межлу собой и в последствии получить плоский массив
-1
С удовольствием прочитаю cool story, где
[].slice.call(arguments, 0)
стал узким местом, да и не одним v8 едины.+4
В коде подобных библиотек — вполне может стать. Дело даже не в том, что приведенный мной вариант быстрее (в 4-30 раз), а в том, что вся функция не будет оптимизирована. Если эта библиотека используется на сотнях, или тысячах картинок это может вылиться в видимую задержку.
Абсолютно верно, остальные движки еще медленнее в этом месте: jsperf.com/arguments-spread
да и не одним v8 едины
Абсолютно верно, остальные движки еще медленнее в этом месте: jsperf.com/arguments-spread
+1
А что будет, если дать более или менее «реальную» нагрузку в тесте, oh wait...
+2
del
0
не одним v8 едины
+1
О, Зевс и что? А если завтра что-то измениться, и светлая голова для операции
slice.call(arguments)
добавит оптимизацию, как они сделали с fn.apply
, что тогда? А вы мне микробенчмарки суете, которые r реальному миру имеют довольно посредственное отношение. Ну и главное, что я хотел, писать «За подобное использование arguments стоит бить по рукам» — попахивает снобизмом. +2
Да почему снобизм-то? Если постоянно забивать на подобные мелкие недочеты, весь проект в целом будет работать медленнее, чем мог бы.
+1
Да потому что не будет, в реально проекте, тормозит всё что угодно, но не подобные вещи. Есть просто разные уровни, в библиотеках вроде lodash, такие оптимизации оправданы. НО! Сам lodash существует только потому, что нативные реализации не оптимизированы, хотя ситуация меняется.
И ещё, в идеально мире, Array.from должен был показывать максимальный результат, но мы опять имеем какую-то лажу. Остается только надеяться на ...rest, но…
Прямо сейчас, V8 не оптимизирует функции, где есть try/catch/finally, let, const, for-of и что то там еще.
За это тоже по рукам бить?
P.S. Я знаю, что сейчас про jQuery уже все забыли, но когда компы были слабые, а я переходил с IE6 на Mozilla, никого не смущало, что там уйма таким мест, как в прочем и сейчас. Собственно и код таких популярных решений как React (до 0.12.0, дальше они на ES6 перешли), Angular и других, только подтверждают мой посыл, по рукам никого не бьют.
И ещё, в идеально мире, Array.from должен был показывать максимальный результат, но мы опять имеем какую-то лажу. Остается только надеяться на ...rest, но…
Прямо сейчас, V8 не оптимизирует функции, где есть try/catch/finally, let, const, for-of и что то там еще.
За это тоже по рукам бить?
P.S. Я знаю, что сейчас про jQuery уже все забыли, но когда компы были слабые, а я переходил с IE6 на Mozilla, никого не смущало, что там уйма таким мест, как в прочем и сейчас. Собственно и код таких популярных решений как React (до 0.12.0, дальше они на ES6 перешли), Angular и других, только подтверждают мой посыл, по рукам никого не бьют.
+2
Ох, ребята… Да о чем вы все вообще? Это интерпретируемый язык, что изначально говорит о том, что каждый движок интерпретирует его по своему. А если учесть, что в любой последующей версии любого движка могут прикрутить любую оптимизацию, которая кстати может убить ту оптимизацию, которую проделал разработчик, то вся эта оптимизация со стороны разработчика становится погоней за миражом.
Пишите код, получайте от этого удовольствие и не забывайте о производительност и эффективности своих алгоритмов(большое «О»). Но заниматься оптимизацией под лупой в интерпретируемом языке — неблагодарное дело, по причине, которую я описалвыше, кроме совсем явных мест.
Другое дело, если вы точно знаете под какой движок пишите и излазили его исходники вдоль и поперек.
Так же согласен с предыдущим оратором. Посмотрите на код современных не ES6 библиотек. Где там читаемость? Там сплошная оптимизация.
Пишите код, получайте от этого удовольствие и не забывайте о производительност и эффективности своих алгоритмов(большое «О»). Но заниматься оптимизацией под лупой в интерпретируемом языке — неблагодарное дело, по причине, которую я описалвыше, кроме совсем явных мест.
Другое дело, если вы точно знаете под какой движок пишите и излазили его исходники вдоль и поперек.
Так же согласен с предыдущим оратором. Посмотрите на код современных не ES6 библиотек. Где там читаемость? Там сплошная оптимизация.
+1
Потому что каждой оптимизации своё место. Обращать внимание на arguments и пр. примеры из проблем V8 имеет смысл, если вы ожидаете, что этот метод будет вызываться десятки тысяч раз. К примеру вы пишете игру, и ваша задача повысить FPS. Там и asm.js не грех использовать.
Весь остальной же код должен быть в первую очередь хорошо читаемым, легко расширяемым, и т.д.
Проблема любых видов экономии на спичках заключается в том, что это самая крайняя мера. Перед тем как заняться ею, необходимо исправить другие проблемы, которые дадут вам выигрыш на 1-2 порядка по производительности. Например в особо важных местах отказаться от любой реактивщины. Оптимизировать работу с DOM. Параллельные запросы, вместо последовательных. Ленивые вычисления. Ну и т.д.
Тут ребята изолируя тело try-catch конструкции в отдельный метод до 1600% прироста производительности получают. Но это не повод так делать, в нормальном коде, который не требует запредельной производительности. Никто не заметит, что ваш метод выполнился за 0.001ms вместо 0.0001ms.
Весь остальной же код должен быть в первую очередь хорошо читаемым, легко расширяемым, и т.д.
Проблема любых видов экономии на спичках заключается в том, что это самая крайняя мера. Перед тем как заняться ею, необходимо исправить другие проблемы, которые дадут вам выигрыш на 1-2 порядка по производительности. Например в особо важных местах отказаться от любой реактивщины. Оптимизировать работу с DOM. Параллельные запросы, вместо последовательных. Ленивые вычисления. Ну и т.д.
Тут ребята изолируя тело try-catch конструкции в отдельный метод до 1600% прироста производительности получают. Но это не повод так делать, в нормальном коде, который не требует запредельной производительности. Никто не заметит, что ваш метод выполнился за 0.001ms вместо 0.0001ms.
+1
Для этого в ES6 придумали spread операторSpread оператор хорош, но это ES6. И, кстати, далеко не факт, что такой код в ближайшее время будет оптимизирован. Не так давно мелькала статья, с причинами не-оптимизации. И по большому счёту, чтобы туда не угодить, нужно свой код под лупой разглядывать. Для некритичных к производительности участкам кода ― в этом смысла мало.
Не вижу никакого криминала в старом добром
Array.prototype.slice.call(arguments)
Вот правда, что-то я замешкался, относительно ещё и concat-а в этом месте… smelukov, а зачем он тут?
0
Вот здесь объяснил — habrahabr.ru/post/276913/#comment_8768303
0
Возможно Вы в первый раз сталкиваетесь с расширением встроенных конструкторов?
-5
Хорошо бы с этим более никогда не сталкиваться. PrototypeJS я думаю хватило всем выше крыши.
Правильным будет считать только подходы:
1. с расширением symbol-ми (и то под большим вопросом)
2. с наследованием от стандартных объектов
3. внутре-модульной реализацией всего что нужно
А для прямого засорения штатных прототипов не осталось ровным счётом ни одного аргумента.
Правильным будет считать только подходы:
1. с расширением symbol-ми (и то под большим вопросом)
2. с наследованием от стандартных объектов
3. внутре-модульной реализацией всего что нужно
А для прямого засорения штатных прототипов не осталось ровным счётом ни одного аргумента.
0
Или, возможно, Вы о том, что можно было не расширять конструктор, а просто вернуть функцию allSettled из модуля?
Как вариант. Но здесь на вкус и цвет… Я реализовал так.
Как вариант. Но здесь на вкус и цвет… Я реализовал так.
-4
Во первых, большое спасибо за статью, тема промисов действительно интересна и полезна.
На счёт расширения конструктора, я постараюсь аргументированно ответить.
Я считаю, что это отнюдь не на вкус и цвет. Сам принцип модульности заключается в том, что то, что происходит внутри модуля — остаётся внутри модуля.
Допустим я подключил ваш Image preloader и использую его.
Допустим, я подключил так же другую утилитарную либу N, которая тоже вдруг решила, что нативным Промисам страсть как не хватает так сказать статического свойства allSettled. Я получу конфликт имён и грязно ругаю обе библиотеки, которые позволяют себе такую наглость.
Патчинг свойств глобального Promise нисколько не лучше глобальных переменных и несёт всё те же проблемы и подводные камни.
Да, я бы хотел получить функцию allSettled как экспорт из модуля, раз уж мы работаем в модульной среде. Если мне страсть как понадобится положить его в конструктор Promise, я это смогу сделать в любой момент.
Ваш способ не оставляет выбора.
На счёт расширения конструктора, я постараюсь аргументированно ответить.
Я считаю, что это отнюдь не на вкус и цвет. Сам принцип модульности заключается в том, что то, что происходит внутри модуля — остаётся внутри модуля.
Допустим я подключил ваш Image preloader и использую его.
Допустим, я подключил так же другую утилитарную либу N, которая тоже вдруг решила, что нативным Промисам страсть как не хватает так сказать статического свойства allSettled. Я получу конфликт имён и грязно ругаю обе библиотеки, которые позволяют себе такую наглость.
Патчинг свойств глобального Promise нисколько не лучше глобальных переменных и несёт всё те же проблемы и подводные камни.
Да, я бы хотел получить функцию allSettled как экспорт из модуля, раз уж мы работаем в модульной среде. Если мне страсть как понадобится положить его в конструктор Promise, я это смогу сделать в любой момент.
Promise.allSettled = require('promise-ext-settled');
Ваш способ не оставляет выбора.
+1
Да, возможно стоит обдумать этот момент и не выносить allSettled в конструктор, т.к. в данном случае это не полифил, которым расширяется прототип
0
Счел Ваши мысли вполне логичными и, так как allSettled не является полифиллом и не расширяет прототип, то сделал из него полноценный модуль без внесения изменений в нативные конструкторы ;)
+1
Можно еще вот так делать. Что, кстати, и рекомендует делать автор bluebird, из-за преемственности со стандартным try-catch потоком.
.then(function() {
throw "Error";
})
.catch(function() {
return "Fallback";
})
.then(function(result) {
console.log(result);
// Получаем fallback
});
+1
Получается, что, если асинхронная операция будет выполнена успешно, то выполнится onFulfilled callback в первом then, а далее onFulfilled callback во втором then.
Но что, если асинхронная операция завершится неудачей? Выполнится onRejected callback в первом then, а затем(внимание!) onFulfilled callback во втором then.
Почему? Смотрите выше правило для then-callback.
Исходя из него — чтобы вызвать следующий onRejected callback(которого кстати нет), необходимо: либо вернуть промис, который будет rejected, либо выбросить исключение.
А вот тут огромная СПАСИБА! :)
Я раньше оборачивал в новый Promise, теперь буду знать.
0
Sign up to leave a comment.
Fallback-действия в ES6 Promise