Задать вопрос
  • Как через window сделать глобальную переменную const?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Через defineProperty()
    Object.defineProperty(window, "test", {
      value: "QnA"
    });
    Присвоение нового значения ошибки не вызовет, но и не сработает: сохранится указанное значение.
    проверки
    test = "X"; 
    test // "QnA"
    
    var test = "Y";
    test // "QnA"
    
    window.test = "Habr";
    test // "QnA"
    
    const test = "Z" // Uncaught SyntaxError: redeclaration of var test

    Тут не указано writable: false – оно и так по умолчанию false. И именно это свойство дескриптора определяет, можно ли назначить новое значение.

    Если переменная/свойство уже были декларированы ранее, то надо явно указать writable: false, чтобы свойство стало «константным».
    var test = "Habr";
    
    Object.defineProperty(window, "test", {
      value: "QnA",
      writable: false,
    });
    Ответ написан
    Комментировать
  • Как добавить в Express.js обработчик res.send()?

    @StiflerProger
    Через use, перепиши функцию response
    app.use(function (req, res) {
        var send = res.send;
        res.send = function (body) {
            // тут что надо делай
            send.call(this, body);
        };
    });
    Ответ написан
    1 комментарий
  • Какая разница между await и Promise?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    (async () => {
      const result = await {
        then(resolve) {
          console.log('Привет сахар');
          setTimeout(() => resolve(10), 3000);
        }
      };
      console.log('Ух ты, данные из таймера:', result);
    })();

    (async () => {
      try {
        await {
          then(_, reject) {
            console.log('Привет сахар');
            reject(new Error('Ошибочка'));
          }
        };
        console.log('Это никогда не выполнится');
      } catch (e) {
        console.log('Ух ты, эксепшн:', e);
      }
    })();

    console.log('Промисы никуда не делись?', (async () => {})() instanceof Promise)
    Ответ написан
    Комментировать
  • Какая разница между await и Promise?

    sergiks
    @sergiks Куратор тега JavaScript
    ♬♬
    Promise – сложная штуковина для асинхроты всякой, с кучей методов.
    Зачем забивать себе голову, если можно зайти на QnA, задать вопрос и поджидать await готовый ответ.
    В это время не сидеть-тупить в экран, а пойти чайку попить. Как появится ответ — продолжим дальше.
    Ответ написан
    7 комментариев
  • Как nodejs обрабатывает десятки тысяч соединений?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Асинхронное программирование
    Седой и строгий
    Самые большие затраты на ввод/вывод. Грубо говоря, если один запрос 90% времени ожидает I/O, то в случае 10 000 конкурентных запросов сервер 9,999% времени находится в ожидании I/O, а асинхронное выполнение позволяет это время использовать с пользой или попросту списать. В то время как многопоточный сервер, обрабатывающий 10k соединений, 90% времени будет тратить на переключение контекста, да и то, если памяти хватит.
    Ответ написан
    3 комментария
  • IT с нуля? или кардинальное изменение?

    @Qualiant
    Вам лучше вообще не входить в IT. Один из ценнейших навыков программиста - самостоятельный поиск информации. Те, кто хотят научиться программировать - садятся и учатся сами. Находят туториалы, читают их, учатся. Методом проб и ошибок учатся отличать плохое от хорошего и т.д.
    Ответ написан
    4 комментария
  • Могу ли я в чистом javascript в асинхронной функции подождать возникновения события?

    bingo347
    @bingo347 Куратор тега JavaScript
    Crazy on performance...
    Первое что нужно понимать, что async/await - это всего лишь синтаксический сахар над промисами, а значит имеет все особенности работы с ними:
    Во-первых, промис может разрешится (или отклонится, но в этой задаче reject не нужен) только единожды. Это сильно отличает их от событий, которые могут происходить многократно.
    Во-вторых, промисы обрабатываются на особой фазе event loop называемой microtasks, что опять же отличается от событий, которые выполняются на другой фазе (tasks). Это означает, что обработка промиса (колбэк метода then, или сахар над ним в виде await оператора) всегда произойдет асинхронно от возникновения события. Это накладывает ряд ограничений, например не получится сделать preventDefault у объекта или не получится запустить действия требующие синхронной работы из trusted события (play не muted video/audio, вход в фулскрин и тд).

    В простом варианте можно слушать событие разово, для чего можно использовать параметр once. Так же для оптимизации можно использовать параметр passive, так как нам все равно поздно вызывать preventDefault, а в некоторых случаях это может дать нам оптимизацию. Ну и управлять параметром capture попросту бесполезно, так как обработка будет в любом случае после обеих фаз. В итоге для этого можно пользоваться такой функцией хелпером:
    function listenOnce(target, event) {
        return new Promise(resolve => {
            target.addEventListener(event, resolve, {
                once: true,
                passive: true
            });
        });
    }
    
    // использование
    const event = await listenOnce(document, 'DOMContentLoaded');
    console.log(event);


    Если же нужно слушать событие многократно, то разумно обернуть прослушивание события в асинхронный итератор. Здесь так же присутствуют все ограничения связанные с промисами, но за счет того, что у нас будет итератор по множеству промисов, мы сможем слушать событие многократно. так же тут нужно предусмотреть возможность отписаться от события. Хелпер для данного случая получится такой:
    function listen(target, event) {
        let currentResolve = () => {};
        const handler = event => currentResolve({value: event, done: false});
        return {
            [Symbol.asyncIterator]() {
                target.addEventListener(event, handler, {passive: true});
                return {next: () => new Promise(resolve => {
                    currentResolve = resolve;
                })};
            },
            stop() {
                target.removeEventListener(event, handler);
                currentResolve({done: true});
            }
        };
    }
    
    // использование
    for await(const event = listenOnce(window, 'scroll')) {
        console.log(event);
    }
    
    // с отпиской
    const eventIterator = listenOnce(window, 'scroll');
    let count = 10;
    for await(const event = eventIterator) {
        console.log(event);
        if(--i === 0) {
            eventIterator.stop();
        }
    }
    Ответ написан
    4 комментария
  • Что такое обратный вызов в программировании?

    bingo347
    @bingo347
    Crazy on performance...
    Что такое обратные вызовы?
    Я знаю только что это функция которая передается как аргумент в другую функцию.
    В принципе, можно и так сказать. Если быть более точным - это вызов функции переданной в качестве аргумента.
    Почему они так называются?
    Это игра слов. На английском callback - это не только обратный вызов, но и обратный звонок (по телефону). Данная абстракция позволяет вызываемому коду вызвать вызывающий код, подобно тому как собеседник может перезвонить Вам позднее, если Вы сообщите ему куда.
    В чем их смысл и зачем нужны?
    В принципе я уже ответил, они нужны для возможности вызываемому коду вызвать вызывающий код. Это позволяет строить высокоуровневые абстракции, вроде обобщенных функций или асинхронных функций.
    Обобщенные функции позволяют не писать однотипный код, снижая тем самым вероятность ошибок, а с помощью обратных вызовов они могут принимать в себя фрагменты кода, которые могут меняться от использования к использованию. Для примера, абстрагируем цикл от 0 до n на C:
    // абстракция цикла
    void each(int n, void (*callback)(int, void*), void* closure_data) {
      if(n <= 0) { return; }
      for(int i = 0; i < n; i++) {
        (*callback)(i, closure_data);
      }
    }
    
    // колбэк - тело цикла, вариант 1
    void cb_body1(int i, void*) {
      printf("%d", i);
    }
    
    // колбэк - тело цикла, вариант 2
    void cb_body2(int i, void* acc) {
      int* normalized_acc = (int*)acc;
      *normalized_acc += i;
    }
    
    int main() {
      each(10, cb_body1, null); // напечатает строки 0, 1, ...9
    
      int result = 0;
      each(10, cb_body2, &result); // посчитает в result сумму чисел от 0 до 9
      printf("%d", result);
      return 0;
    }

    Асинхронные функции позволяют выносить долгие вычисления в фоновые потоки, тем самым не блокируя основной поток. А свой результат, когда он готов, они передают в обратный вызов.

    Так же стоит заметить, что во многих высокоуровневых языках наряду с обратными вызовами используется механизм замыканий, который позволяет объявлять функции внутри других функций и захватывать окружающие переменные. Но нужно понимать, что это лишь компиляторный сахар, и на самом деле в функцию просто передаются указатели на захваченные переменные в качестве аргументов, подобно тому, как я сделал это руками в примере выше, с помощью аргумента closure_data в функции each. Обычно компилятор создает для этого анонимные структуры (C++, Rust) или анонимные классы (C#), которые хранят указатель на функцию и указатели на окружение. А в некоторых языках, например в js, замыкания возведены в абсолют, и каждая функция является замыканием.
    Ответ написан
    2 комментария
  • Что такое обратный вызов в программировании?

    andreydobrin
    @andreydobrin
    Сложно , но это пока
    Все очень просто:
    Вы правильно сказали, что это функция, передающаяся как аргумент в другую функцию:
    пример с js
    function  first(callbak){
    ----здесь пишем код функции----
    ---- здесь можно записать код "функции обратного вызова" 
    и она сработает тогда, когда выполнится функция first()----
    }

    Простым языком - есть одна функция и у нее в параметре другая. Сперва выполнится сама функция, а потом та, которая является аргументом этой функции.
    Ответ написан
    Комментировать