1. JavaScript / Говнокод #15974

    +163

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    function loading() {
         $('#close').hide(function() {
          $('#loading').show(function () {
            setTimeout(function(){
                $('#loading2').show(function() {
                setTimeout(function(){
                  $('#loading3').show(function () {
                    setTimeout(function(){
                      $('#vk').show(function() {
                        setTimeout(function(){
                         $('#odn').show(function() {
                          setTimeout(function(){
                            $('#fb').show(function() {
                              setTimeout(function(){
                               $('#tw').show(function () {
                                $('#geo').show();
                                setTimeout(function(){
                                  payment();
                                },1300);
                               });
                              },1600);
                            });
                          },1700);
                         });
                        },1400);
                      });
                    },1600);
                  });
                },1900);
              });
            },1600);
          });
         });
         }

    Из исходного кода сайта, "раскрывающего" анонимов на аск.фм

    Запостил: TRANE73, 13 Мая 2014

    Комментарии (94) RSS

    • Вот до чего людей отстутсвие async доводит. js-бляди соснули.
      Ответить
      • Ещё циклов и локальных переменных у них в языке нет. Совсем тяжко.
        Ответить
        • Совсем тролсто.
          Ответить
          • З.Ы. Сейчас набегут жсоёбы, и начнут рассказывать сказки, что мы ничего не понимаем в концепции этого прекрасного языка, что асинк не нужен, т.к. все можно замутить на комбинаторах, что скопы не нужны, что фор нормальный, что те, у кого типы не туда приводятся - мудаки, не читавшие ман и т.п.
            Ответить
            • Набегаю.
              > прекрасного языка
              прекрасный язык, мне очень нравится
              > фор нормальный
              фор нормальный
              > типы не туда приводятся
              Инт неявно приводится к даблу - пожалуй, единственная проблема. Возникает она, когда начинаешь использовать жс не по назначению вместо сишки в погоне за перфомансом. В этом случае следует начать спокойно дышать, выбросить из головы богомерзкие мысли и взять более уместный язык.
              Ответить
              • cleaned
                Ответить
              • >прекрасный язык, мне очень нравится
                Удваиваю.
                Вот пусть борманд первый и бросает на нём писать.
                Ответить
            • > асинк не нужен, т.к. все можно замутить на комбинаторах
              На JS то? Их использовние же выглядеть будет как говно не меньше чем у топикстартера
              Ответить
              • sequence([
                    function (a) {
                        return a + 1;
                    },
                    function (b) { // b = a + 1
                        return b + 1;
                    }
                })
                Вот как-то так. Ужасно, конечно.
                Ответить
            • >З.Ы.
              Расчет на то, что у юзеров отключены ники?
              Ответить
            • > Сейчас набегут жсоёбы
              Посмотрите на главную... Зачем Вы их созвали? :)
              Ответить
        • > циклов
          Циклов там дохуя:

          for (a in b)
          for each (a in b)
          for (a of b)

          Вот только первый - неюзабельное говно, второй успели объявить устаревшим до его внедрения, а третий пока только в огнелисе ;)
          Ответить
          • >Циклов там дохуя:
            for each (a in b)
            SyntaxError

            for (a of b)
            SyntaxError

            Цикл for там ровно 1 (один).
            for (var a=0;a<n;++a){...}
            Ответить
            • > SyntaxError
              Ну толсто же... В новых фф, к примеру, они работают:
              for each (a in {x:5, y:10}) { console.log(a); }
              5
              10
              
              for (a of [1,2,3]) { console.log(a); }
              1
              2
              3
              > Цикл for там ровно 1 (один)
              Вменяемо работающий и кроссплатформенный цикл там ровно 1 (один).
              fxd

              В крестах, пыхе, жабе, шарпе, питоне, да и в других языка уже давным-давно есть форич для коллекций. И только жабоскриптоёбы продолжают жрать кактус с сишным for'ом, и утверждать, что все нормально, так и надо.
              Ответить
              • И тут я такой врываюсь в тред и напоминаю, что жавоебский xml парсер не может в форич.
                Ответить
                • Более того - жаваскриптоёбский дом тоже в него не может.
                  Ответить
              • >В новых фф, к примеру, они работают:
                В фф много чего полезного работает - генераторы-итераторы, yield, let.
                Проблема в том что больше нигде кроме фф они не работают.
                Ответить
                • Пусть пользователи альтернативных браузеров страдают.
                  Жаль только, что огнелис ВНЕЗАПНО стал говном.

                  P.S. Пишу с 28-го, брата никогда не было.
                  Ответить
                  • cleaned
                    Ответить
                    • >система с 500 мб памяти
                      Тарасокомп?
                      Ответить
                    • > За какие-то 20 мин работы система с 500 мб памяти падает.
                      А результат GetElementByTagName никуда не сохраняешь случаем? Сейчас затестим.
                      Ответить
                      • setInterval(function() { var x = document.getElementsByTagName('div'); }, 0);

                        Запускалось 10 таких таймеров.

                        До теста - 1.3Gb виртуальной, 0.5Gb юзается
                        Во время теста - 1.3Gb виртуальной, 0.5Gb юзается

                        Разницы никакой. Видимо или пофиксили, или эти 500 мег - порог для сборщика мусора.

                        Кинь код, которым получалось завалить, если он у тебя сохранился.
                        Ответить
                    • ФФ не перезапускал 98 дней. Может я как-то не так им пользуюсь (и памяти у компутера больше), но как-то проблем не замечал. Утечку с использованием getElementByTagName воспроизвести не удалось.
                      Ответить
                    • ПС. На данный момент открыта 201 закладка.
                      Ответить
                      • Чем измерял? Мне лениво ставить аддончики или считать ручками по sessionstore, посчитал по скруллам, около 450±32.
                        Ответить
                        • У меня установлен MozRepl, он дает через ж.скрипт доступ к эелентам интерфейса. Жизнь процесса можно посмотреть:
                          $ pgrep firefox | xargs -I{} echo "stat /proc/{}" | sh
                          Ответить
              • for in - разве не foreach ?
                Ответить
            • З.Ы. О скопах:

              ПРИШЛО ВРЕМЯ ЗАМУТИТЬ СКОП.
              СКОП САМ НЕ ЗАМУТИТСЯ.
              ЗАВЕРНИ ЕГО В ФУНКЦИЮ, ЗАВЕРНИ ЕЩЕ РАЗ.
              ЗАЧЕМ МНЕ НУЖЕН LET, У МЕНЯ НЕТ ВРЕМЕНИ ЕБАТЬСЯ С НИМ.
              ЛУЧШЕ ЕЩЕ РАЗ ОБЕРНУТЬ СКОП В ФУНКЦИЮ.
              Ответить
            • О, уже капсболд пошел.
              Ответить
              • >О, уже капсболд пошел
                Я тебя немного просвещу, чтоб ты не выдавал очередную порцию херни.
                Капсболд - это когда текст написан одновременно КАПСОМ и болдом.
                Ответить
                • Мой фаллос так раскален, что обращает в прах на дистанции десять шагов. Нагнись, я войду...
                  Ответить
                • Ответить
        • Это же толсто, да?
          Ответить
          • Отчасти. Тут напрашивается какая-то циклоподобная конструкция с обходом массива (как sequence у Борманда)

            Что-то такое:
            function hide(obj){ return function(){ $(obj).hide(this.callback); }; }
            function show(obj){ return function(){ $(obj).show(this.callback); }; }
            function timeout(time){ return function(){ setTimeout(this.callback, time); }; }
            
            function sequence(array, callback){
              var i = -1;
              var context = {
                callback: function(){
                  ++i;
                  if(i >= array.length){
                    callback();
                    return;
                  }
                  array[i].call(this);
                }
              };
              context.callback();
            }
            
            function loading() {
              sequence([
                hide('#close'),
                show('#loading'),
                timeout(1600),
                show('#loading2'),
                timeout(1900),
                show('#loading3'),
                timeout(1600),
                show('#vk'),
                timeout(1400),
                show('#odn'),
                timeout(1700),
                show('#fb'),
                timeout(1600),
                show('#tw'),
                function(){
                  $('#geo').show();
                  this.callback();
                },
                timeout(1300),
                payment
              ]);
            }
            Ответить
            • Ну циклы и локальные переменные же в js есть? Скажите, что они есть?

              То есть, стандартного await нет, все должны пилить все реально удобно, реально падсибя?
              Ответить
              • Циклы, локальные переменные и замыкания есть. await нет, падсибя уже что-то реализовали в нескольких библиотеках.
                P.S. array[i].call(this); надо заменить на array[i].call(context);, т.к. внутри функции вызывающий может его потерять. Но свой код я не ещё запускал - может ещё баги есть.
                Ответить
    • cleaned
      Ответить
    • А если серьёзно, то как обычно оформляют подобную асинхронную лапшу, чтобы было красиво? Мне приходит только разбить на функции.
      Ответить
      • Хз. не могу найти подробного описания, но я его знал под названием "conveyor belt pattern". Т.е. у нас есть список, который мы можем дополнять по мере необходимости, считывающий код, который выполняет инструкцию в текущей ячейке списка и ждет окончания, затем переходит к следующей ячейке и т.д.
        Т.е. у ячейки должно быть два метода принимающие "рабочего": "старт" и "финиш". Старт вызывает у "рабочего" "ждать", а "финиш" вызывает у рабочего "следующий". Своего рода комбинация посетителя со стейтом.
        Ответить
        • Deferred из Twisted?
          Ответить
          • Не, http://flash-ripper.com/archives/000390.php отголоски далекого прошлого. Самой статьи уже давно нет, да и автор по-ходу давно Флешем не занимается, тут какие-то остатки описания остались. Я думаю, что автор и Твистед не пересекались в жизни, по крайней мере по времени, это почти совпадает с созданием проекта.
            Ответить
            • http://darrennewton.com/2013/11/16/evented-arrays-a-javascript-conveyor-belt/
              оно?
              Ответить
              • function cell(task, time) {
                    this.task = task;
                    this.time = time;
                }
                
                cell.prototype.start = function (worker) {
                    this.work();
                    this.timer = setTimeout(this.stop, this.time, worker);
                };
                
                cell.prototype.work = function () { this.task(); };
                
                cell.prototype.stop = function (worker) { worker.next(); };
                
                function worker() {}
                
                worker.prototype.cells = [];
                
                worker.prototype.next = function () {
                    this.cells.shift();
                    if (this.cells.length) this.cells[0].start(this);
                };
                
                worker.prototype.add = function (task, time) {
                    this.cells.push(new cell(task, time));
                };
                
                var conveyor = new worker();
                
                for (var i = 0; i < 10; i++) {
                    conveyor.add(function (i) {
                        return function () { console.log("Step #" + i); };
                        }(i), 100);
                }
                
                conveyor.next();
                // Step #1
                // Step #2
                // Step #3
                // Step #4
                // Step #5
                // Step #6
                // Step #7
                // Step #8
                // Step #9

                Может и не дословно, но примерно так.
                Ответить
      • >А если серьёзно, то как обычно оформляют подобную асинхронную лапшу, чтобы было красиво?
        Гугли javascript promises, js deferred
        http://wiki.commonjs.org/wiki/Promises
        https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

        Как-то так.
        Думаю тут что-то от монад и cps есть.
        Ответить
        • У deferred есть несколько проблем, которых нет у обычных колбеков: повторное использование, совместное использование и обработка ошибок.
          Т.е. например, если у нас есть элемент, который может загружать в себя картинку больше одного раза, и мы хотим реагировать на загрузку одинаково каждый раз: deferred не сможет это сделать, т.как он срабатывает только первый раз, когда событие произошло, потом его можно только удалять.
          Предположим, все тот же элемент, но у нас есть два других участка кода, которые хотят получать сообщения о смене картинки, пердположим один из обработчиков сообщения бросил ошибку: что делать во втором обработчике? Считать ли, что deferred завершился с ошибкой (и вызывать соответствующий метод) или продолжать работать в обычном режиме? Когда у нас есть просто колбеки такие вопросы не возникают.
          Вобщем, я к тому, что deferred - плохая абстракция.
          Ответить
          • >которых нет у обычных колбеков: повторное использование, совместное использование и обработка ошибок.
            Они как раз созданы чтобы решить эти проблемы.

            >пердположим один из обработчиков сообщения бросил ошибку: что делать во втором обработчике?
            >Считать ли, что deferred завершился с ошибкой (и вызывать соответствующий метод)
            Всё зависит от заданной монады стратегии исполнения.
            Ответить
            • Ну тогда это значит, что мы не сможем инкапсулировать эту стратегию, и еще хуже, если мы выступаем в качестве провайдера сервиса, то это значит, что несколько клиентов могут захотеть разные стратегии...
              Ответить
        • > монад и cps
          Monad + cps = Control.Monad.Cont(T)
          Это адский вынос мозга
          Ответить
      • Чтобы красиво - await.
        Ответить
        • Предположим, у тебя есть await. Покажи, каким красивым стал код.
          Ответить
          • Сегодня я постою на стороне async/await:
            async function loading() {
                await $('#close').hide();
                var divs = ["#loading", "#loading2", ...];
                var delays = [1600, 1900, ...];
                for (var i = 0; i < divs.length; ++i) {
                    await $(divs[i]).show();
                    await sleep(delays[i]);
                }
            }
            Ответить
            • Как в этом случае работают await? Я не понимаю. В JS у нас всегда ровно один поток.

              Если этот async эквивалентен фьючерсу, а await - это get, тогда для корректной работы нужно два потока, и тогда все три await - лишние.

              Даже если магический await sleep сообщает шедулеру, что он может переключить нас на другую корутину (ещё и с указанием, когда разбудить), нужно полноценная поддержка корутин с суспендом/резьюмом, а такого рантайм js вроде бы никогда не умел (в lua такое есть, но и там сложно заранее узнать, когда тебя разбудят).
              Ответить
              • Но ведь мы предположили, что в этом гипотетическом жс есть поддержка асинк/авейт?

                Асинк метод в шарпе - это необычный метод - он компилится то ли в конечный автомат, то ли в лапшу из коллбеков. И возвращает он future. А await проверяет future на завершеность, и если не завершено - отдает управление. Причем авейт можно юзать ТОЛЬКО в асинк методах, т.к. остальные нельзя просто взять и прервать (понадобится поддержка короутин и т.п. т рантайма).

                Короче это просто красивый и удобный сахар вокруг фьючерсов.
                Ответить
                • > он компилится то ли в конечный автомат, то ли в лапшу из коллбеков
                  Ага. И исключения работают неадекватно. Полумера. Не нужно.
                  Ответить
                  • > Полумера. Не нужно.
                    А что ты хотел от синтаксического сахара? :)
                    Ответить
              • Кстати, можно еще и вот так юзать (псевдошарпокод с точностью до имен классов):
                // на самом деле этот метод возвращает Future<int>
                async int someShit() {
                    Future<int> r1 = calculateSomeShit(); // считает что-то большое в отдельном треде
                    Future<int> r2 = calculateAnotherShit(); // тоже считает что-то большое
                    return await r1 + await r2;
                }
                Ведь эти async/await не более чем синтаксический сахар для ожидания future.
                Ответить
                • > можно еще и вот так юзать
                  так это основной сценарий использования фьючерсов :)
                  запустить один потенциально блокирующий процесс в бэкграунд, поделать, что-то самому (например, запустить ещё один процесс), обработать результаты. Фьючерс, на котором сразу делают get(), практически бесполезен.
                  Ответить
                  • Ну я просто хотел показать, что этот await к самому вызову метода calculateSomeShit() никакого отношения не имеет.

                    > Фьючерс, на котором сразу делают get(), практически бесполезен.
                    Да, согласен.
                    Ответить
                    • > Да, согласен.
                      Но await это не get :)
                      Ответить
                    • > await к самому вызову метода calculateSomeShit() никакого отношения не имеет
                      это из типа видно :) в шарпе Task<T> (точнее, всё, что умеет GetWaiter()), но мы-то знаем, что это всё монады

                      > Но await это не get :)
                      вот это я всё никак не пойму, попозже ещё повтыкаю.
                      Ответить
                      • > вот это я всё никак не пойму
                        Что-то в духе "если задача уже выполнена - берем ее результат и продолжаем выполнять следующий кусок, если нет - просим задачу выполнить следующий кусок когда она завершится".

                        P.S. Блин, вот спорю-спорю с шарпеями, а ведь шарп потихоньку осваивается, и что самое ужасное, начинает мне нравиться...
                        Ответить
                        • > начинает мне нравиться
                          Попиши в вижуалстудии, должно отпустить
                          Ответить
                        • >Блин, вот спорю-спорю с шарпеями, а ведь шарп потихоньку осваивается, и что самое ужасное, начинает мне нравиться...
                          Тарас тоже так начинал.
                          Обилие синтаксического сахара, много зачастую бесполезных фич и сложность стандарта - это на любителя. Кстати в этом плане шарп во многом схож крестами, только с managed-среда с clr и gc.
                          С выходом нового стандарта мне всё больше начинают нравиться кресты, точнее их сабсет - как нынче модно писать. Обилие стандартных эффективных многопоточных блоков - это вообще небесный дар.
                          Ответить
                          • Так что это, подождите, сисярп - это не улучшенный вариант явы, а крестоблядство с GC? А как же... А я... Но я-то думал...
                            Ответить
                          • > Кстати в этом плане шарп
                            во многом схож крестами, только с
                            managed-среда с clr и gc.

                            и наконец обошлись без сырых указателей
                            Ответить
                            • > обошлись без сырых указателей
                              В unsafe вроде есть.
                              Ответить
                • > return await r1 + await r2;
                  Divide et impera.
                  Это еще римляне знали. MS просто заимствовали стратегию успеха.
                  Ответить
                  • А тем временем кое-кто все еще сосет.
                    Ответить
                    • >А тем временем кое-кто все еще сосет.
                      Подробности твоей личной жизни мне не особо интересны.
                      Ответить
                      • Пи, а почему ты все принимаешь на свой счет? Нет, ты правильно угадал, НО КАК???
                        Ответить
                    • С проглотом?..
                      Ответить
              • >Как в этом случае работают await?
                Загугли, ёба, во что декомпилируется await в C#.
                Ответить
            • в общем, похоже, твой пример сводится примерно к следующему
              var f = async(function () {
                var i, divs = [ /* ... */ ], delays = [ /* ... */ ];
                uiThread.shedule(function () { $('#close').hide(); });
                for (i = 0; i < divs.length; ++i) {
                  uiThread.shedule(function (div) { $(div).show(); }, divs[i]);
                  sleep(delays[i]);
                }
              });
              Ответить
              • мдя, это не работает, т.к. не известно, когда ui тред закончит показывать элемент. Если он будет занят разгребанием эвентов, будет показана сразу пачка объектов. Нужно в функции ui треда слать сигнал обратно, что можно начинать спать. В go для такого есть каналы.
                Ответить
              • > сводится примерно к следующему
                async/await не требуют никаких дополнительных потоков. И выполняются они в строгом порядке, как колбечная лапша из топика.

                Сейчас попробую изобразить это на жс...
                Ответить
                • > async/await не требуют никаких дополнительных потоков. И выполняются они в строгом порядке, как колбечная лапша из топика.
                  +
                  В данном случае это просто буквы, код с этими буквами будет эквивалентен коду без них.
                  Ответить
              • Вот как-то так я себе это представляю (если на время забить на исключения): http://jsfiddle.net/reqfD/

                С исключениями код будет посложнее, но вполне реализуемо (отлавливать в кусках, упихивать во future через что-нибудь в духе raiseException(), и сделать коллбек onException).

                То, что await принимает только одного слушателя - косяк моей рахитектуры, признаю. Да и это всего лишь пример, а не боевая реализация ;)
                Ответить
                • > косяк моей рахитектуры, признаю
                  З.Ы. Можно сделать массив waiter'ов и вызвать их в цикле, но для демонстрации async/await это непринципиально.
                  Ответить
              • > async(function () {
                Хм, а это идея! Ведь жс может кастануть функцию в строку и получить ее исходник. А затем можно распарсить ее и перепидорасить преобразовать await'ы в лапшу из коллбеков...

                И ведь всяко кто-нибудь уже реализовал это для своей любимой ноды жс.
                Ответить
            • > $
              Щта эта?
              Ответить
    • Что-то я не вижу show с такой сигнатурой
      http://api.jquery.com/show/
      Аналогично для hide.
      Ответить
    • показать все, что скрытоХуй.
      Ответить

    Добавить комментарий