• Как сделать анимацию пульсирующего текста?

    @Interface
    Точно так же, как делают любую другую анимацию будь то css или js анимация. Не вижу почему именно для "пульсации" (что бы это не значило) нужен особый подход
  • Фотошоп в ubuntu?

    @Interface
    Nikolay Petyukh, я не хочу вступать в дискуссию на эту тему, но просто для полноты картины: регулярно пользуюсь виндой (как сегодня так и лет 10 назад), макосью и линуксом. У винды определенно есть свои плюсы, но увы я бы сказал, что с ней проблем разительно больше чем на других платформах.

    WSL - штука классная, но увы сырая (я про WSL-1)
  • Try catch или then catch для rest api?

    @Interface
    profesor08, Артем Лукьянов Ну тут справедливости ради код с .then() / .catch() неоправданно запутан.

    Если принять во внимание, что post.id используется дважды.
    А также допустить что id используемый тут Posts.findOne({id: id}) это тоже post.id, то код можно переписать так:

    Promise.all([
        Posts.findOne({id}).exec(),
        Comments.find({id}).exec(),
        Links.find({id}).exec(),
    ])
        .then(([post, comments, links]) => {
            res.json({post, comments, links});
        });


    Что вполне себе нормально читается. Более того, теперь запросы выполняются параллельно, не дожидаясь завершения предыдущего, что в общем случае лучше.
    Код с async/await тут выглядел бы не сильно лучше:
    const [post, comments, links] = await Promise.all([
        Posts.findOne({id}).exec(),
        Comments.find({id}).exec(),
        Links.find({id}).exec(),
    ]);
    res.json({post, comments, links});


    Ситуация меняется, если каждый последующий вызов зависит от предыдущего, а в конце нам интересны результаты каждого вызова. Это можно изобразить примерно так:
    Posts.findOne({id}).exec()
        .then(post => {
            Users.findOne({id: post.authorId}).exec()
                .then(author => {
                    Users.findOne({id: author.invitedBy})
                        .then(invitedByUser => {
                            res.json({post, author, invitedByUser});
                        });
                });
        });

    Я не стал усложнять код дополнительными переменными и старым стандартом языка (кроме async/await конечно).

    Тогда как код с async/await выглядит действительно проще:
    const post = await Posts.findOne({id}).exec();
    const author = await Users.findOne({id: post.authorId}).exec();
    const invitedByUser = await Users.findOne({id: author.invitedBy}).exec();
    res.json({post, author, invitedByUser});


    Но при этом это не единственный способ как можно оформить код без async/await. Так в этом примере с каждым новым зависимым запросом растет вложенность кода. Этого можно избежать, если писать код как-то так:
    Posts.findOne({id}).exec()
        .then(post => {
            return Users.findOne({id: post.authorId}).exec()
                .then(user => ({post, user}))
        })
        //...
        // произвольное количество дополнительных шагов без увеличения вложенности
        //...
        .then(data => {
            return Users.findOne({id: author.invitedBy})
                .then(invitedByUser => ({...data, invitedByUser}));
        })
        .then(data => res.json(data));

    Это не делает его супер читаемым, но сдерживает вложенность на каком-то уровне.

    При этом такой сложный код с .then()/.catch() получается именно в случае если одновременно:
    - каждый запрос зависит от предыдущего
    - нужно получить результаты промежуточных запросов в конце

    В этом случае разница при использовании async/await действительно будет колоссальной.

    Однако, если хотя бы одно условий не выполняется:
    - если запросы независимы друг от друга, то можно (и нужно) использовать Promise.all (см. пример выше)
    - если нас интересует только результат конечного промиса (invitedByUser), то можно переписать код так:
    Posts.findOne({id}).exec()
        .then(post => Users.findOne({id: post.authorId}).exec())
        .then(author => Users.findOne({id: author.invitedBy}).exec())
        .then(invitedByUser => res.json(invitedByUser));

    Что намного проще и сопоставимо по сложности с async/await.

    ---

    Но в целом я с profesor08 согласен и советую использовать async/await как и многие другие современные возможности языка везде где это возможно и оправдано.
  • Try catch или then catch для rest api?

    @Interface
    profesor08, моя конечная цель была конечно не выводить в консоль числа. Иначе можно было и
    console.log(1);
    console.log(2);
    console.log(3);

    обойтись :)

    Я это к тому, что это не замена.

    Приведу другой пример:
    // просто какая-то ресурсоемкая синхронная функция
    function heavyJob() {
        let i = 1e6;
        let s = '';
        while (i--) {
            s += Math.random().toString(36);
        }
        return s.length;
    }
    
    function makeRequest() {
        return new Promise(resolve => setTimeout(resolve, 1000));
    }
    
    function generateFingerprint() {
        const foo = heavyJob();
        return makeRequest(foo);
    }
    
    // ====
    
    function profile(fn) {
        let started = Date.now();
        fn().then(() => { // Вот тут не обойтись без then
            console.log(`Async time: ${Date.now() - started}`);
        });
        console.log(`Sync time: ${Date.now() - started}`);
        started = Date.now();
    
    }
    
    profile(() => generateFingerprint());

    я ожидаю от этого кода, что он выведет что-то вроде:
    Sync time: 497
    ...
    Async time: 1000

    Подобный код может быть использован для мониторинга / анализа node.js сервера.

    ----

    Еще один пример - это когда есть необходимость по разному обрабатывать синхронное и ассинхронное исключения:
    function callAsyncMethod(obj, methodName) {
        try {
            obj[methodName]()
                .catch(err => console.error(`replied with ${err}`));
        } catch(e) {
            console.error(e);
            process.exit(1);
        }
    }


    ----

    ну и еще один пример, это когда ассинхронный вызов находится внутри синхронной функции, которая что-то возвращает, например:
    class Cart {
    
        // ...
    
        send(cart) {
            fetch(cart)
                .then(data => this.eventEmitter.emit('sent', data));
            return this; // это нужно вернуть синхронно не дожидаясь ответа
        }
    
        render() {
            // ...
        }
    
        // ...
    }
    
    // ...
    
    const cart = new Cart();
    
    cart.eventEmitter.on('sent', alert('cart was sent'));
    
    cart
        .send()
        .render();


    или, например, когда нужно вернуть некий requestId:

    function send() {
        const promise = AJAXLibrary.someRequest()
            .then(data => JSON.parse(data)) // вот тут тоже .then()
            .catch(err => null);
        return [promise, AJAXLibrary.currentRequestId];
    }
    
    // ...
    
    const [promise, requestId] = send();
    console.log(`request <${requestId}> started`);
    const data = await promise;


    ---

    То есть по сути все примеры крутятся вокруг того, как вставить некоторый ассинхронный вызов внутрь синхронной функции.
    Оставив ее синхронной.

    P.s. да большинство кейсов можно решить примерно так
    function syncFn() {
        console.log(1);
        (async () => {
            await fetch(...);
            console.log('resolved');
        })();
        console.log(2);
    }

    Но написать .then() будет явно проще и понятнее.

    P.s.P.s. я ни в коем случае не призываю использовать .then() в случаях когда можно использовать async/await.
    Наоборот, я считаю async/await одним из лучших нововведений языка.

    Я просто обращаю внимание на то, что в некоторых очень узких кейсах использовать .then() будет куда проще и понятнее.
  • Try catch или then catch для rest api?

    @Interface
    profesor08, если нужно выполнить и синхронный код после вызова, и отреагировать на результат то без .then() не обойтись. Саму конструкцию с then(), конечно, можно оставить внутри ассинхронной функции, но от .then() избавиться не получиться.

    То есть если нужно чтобы код такого плана:
    function send() {
        console.log(1);
        return new Promise(resolve => setTimeout(resolve, 1));
    }
    
    function main() {
        send()
            .then(() => {
                console.log(3);
            });
        console.log(2);
        
    }
    main();

    выводил в консоль 1 2 3, то не получится .then() заменить на await (не меняя код send).

    Ну или, конечно, я что-то упускаю.
  • Try catch или then catch для rest api?

    @Interface
    xmoonlight, разговор про async/await начал автор вопроса Артем Лукьянов потому что в описании вопроса в закомментированной части как раз таки оно и используется. То есть вопрос изначально о том, что лучше .then().catch() или async/await + try/catch.

    Я не говорил вообще такого: Вы сами придумали.

    Я и не приписывал вам никогда таких слов :)

    Я просто не понимаю вашего ответа, на самом деле.

    try/catch ничего не "блокирует" сам по себе. await не дает исполнится следующим за ним инструкциям, пока не разрешиться промис, но при этом весь остальной код (например, обработчики событий) будут работать без проблем. Наличие или отсутствие try/catch на это не влияет. Поэтому я не говорил бы, что в данном контексте что-то "блокируется", потому что это вводит в заблуждение. Примером блокирующего запроса можно привести синхронный xhr (как я писал ранее) или, например, fs.readFileSync().

    Возможно вам показалось, что альтернативой .then().catch() в коде автора был код такого плана:
    try {
      const { rows, rowCount } = db.querySync(query) // положим querySync синхронная версия db.query
      return res.status(200).send({ rows, rowCount })
    } catch (error) {
      return res.status(400).send(error)
    }

    Тогда мне понятна ваша аргументация против такого подхода.
  • Try catch или then catch для rest api?

    @Interface
    xmoonlight,
    однако, не всё так однозначно, если используют данную конструкцию по сей день.


    Если вы про .then().catch() то ее использование может быть оправдано в случае если вам надо, например
    - и сделать ассинхронный запрос (например) send(...)
    - и выполнить синхронно код сразу после "отправки" запроса
    - и отреагировать на его результат
    function main() {
    send()
    .then(() => {
    console.log('request finished');
    });
    console.log('request sent');
    }
    main();
    Это может быть нужно, если, например, send(...) может бросить синхронное исключение, тогда вы не хотите выводить console.log('request sent');

    Такая конструкция не может быть (насколько мне известно) преобразована в async/await.

    В большинстве же случаев не вижу никаких проблем использовать async/await.
  • Try catch или then catch для rest api?

    @Interface
    xmoonlight, не очень понимаю причем тут потоки.

    Т.к. try catch блокирует дальнейшее исполнение кода и ждёт завершения текущей секции.

    это можно трактовать как: try{} catch(e){} блокирует основной поток js до тех пор пока промис не зарезолвится. Но это конечно не так.

    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function main() {
        console.log(1);
        try {
            console.log(2);
            await sleep(10);
        } catch(e) {
    
        }
        console.log(3);
    }
    
    console.log('outer: 1');
    main();
    console.log('outer: 2');


    Ваш ответ звучит так как-будто 'outer: 2'. Не будет выведно до тех пор пока не звершится (не зарезолвится промис внутри) main. То есть как-будто try / catch превращает функцию в синхронную на манер синхронного XHR. Но это не так.

    Результат будет
    outer: 1
    1
    2
    outer: 2
    3


    Что логично.

    То есть код в примере выше эквивалентен:
    async function main() {
        console.log(1);
        return sleep()
            .catch(() => {})
            .then(() => {
                console.log(3);        
            });
    }


    Если же вы имели в виду то что код после await'а (в рамках той же функции) не будет выполнен пока не промис переданный в await не будет разрешен - то это ожидаемо и работает так же как во втором примере. console.log(3) не будет выполнено до тех пор пока промис вернувшейся из sleep не будет разрешен.

    Так что я согласен с profesor08 не вижу причин не использовать try/catch с async/await. По крайней мере в рамках этой дискуссии
  • Try catch или then catch для rest api?

    @Interface
    try / catch же будет работать с async/await
  • Набивать руку сейчас или в процессе?

    @Interface
    В целом стратегия "вызубрить все наизусть" так себе работает где-бы то не было за пределами образовательных учреждений.
  • Mobx: как работать с денормализованными данными?

    @Interface
    Так вроде как с нормализованными данными это проблема не решается?
    - ненормализованные данные: Если в объекте Cart есть ссылка на User, то при удалении последнего из коллекции, он никогда не соберется GC
    - нормализованные: в объекте Cart указан id пользователя, теперь если убрать User, он соберется GC, но в Cart останется "битый" id

    Я что-то не так понимаю?
  • Как использовать один терминал, для нескольких процессов?

    @Interface Автор вопроса
    Спасибо pm2 выглядит действительно интересно. Покопаюсь с ним еще
  • Как использовать один терминал, для нескольких процессов?

    @Interface Автор вопроса
    Я, честно признаться, имею весьма скудный опыт работы с make. Поэтому хочу уточнить, какие именно проблемы он поможет решить в данном случае. Я так понимаю, область применения у него действительно близкая. Но мне в данном случае нужен какой-то инструмент для объединения выводов нескольких процессов.

    Я примерно представляю как запустить несколько процессов через make. Но не очень понимаю, есть ли в make'е инструменты для требуемого форматирования вывода?

    Я накидал такой вот Makefile:
    .PHONY: all
    all: task1 task2
    
    .PHONY: task1
    task1:
    	echo 'executing task#1'
    	node -e 'setInterval(() => console.log("world"), 1000)' &
    
    .PHONY: task2
    task2:
    	echo 'executing task#2'
    	node -e 'setInterval(() => console.log("hello"), 1000)' &


    Где task1 и task2 - 2 параллельных процесса, пишущих в консоль. При этом это решение похоже (по сути им и является) решением через амперсанд (описаным в тексте вопроса). Разве что цели можно положить в Makefile и запускать их одной командой.

    Не могли вы предложить модификацию этого Makefile, которая приведет вывод к тому, что показано в демке или тому, как выглдяит вывод docker-compose? Или подскажите куда копать?
  • Как использовать один терминал, для нескольких процессов?

    @Interface Автор вопроса
    sim3x, я на самом деле не очень понимаю, чем мне поможет WM. Запустить несколько тайлов с терминалом можно и tmux'е, который мне по описанным выше причинам не подходит. Если вы просто предлагаете использовать тайлы / вкладки / панели / окна с терминалом и не париться с "смешанным выводом", то хорошо, я принимаю ваш совет, но все еще нахожусь в поиске альтернативы
  • Как использовать один терминал, для нескольких процессов?

    @Interface Автор вопроса
    sim3x, к сожалению такое решение не очень удобно для меня. (WM вообще я так понимаю возможен только под линуксом, а сейчас я работаю через Windows -> WSL -> Ubuntu)
    Причем неудобство достаточно велико, чтобы искать альтернативы и задавать вопросы на тостере.
  • Как использовать один терминал, для нескольких процессов?

    @Interface Автор вопроса
    longclaps,
    Я бы так не смог.

    Не переживайте. Все приходит с опытом.
    На кроссплатформе трудишься? А зачем?

    не очень понял вопроса
  • Компилятор ругается "pivot is undefined", а почему?

    @Interface
    Приведите, пожалуйста, полный код для воспроизведения ошибки.
  • Сервер статус 0?

    @Interface
    AsdfAsdfSK, можете отметить ответ как решение, если он является таковым
  • Сервер статус 0?

    @Interface
    AsdfAsdfSK, код можно выполнить с помощью функции eval. почитайте про нее. Но кажется вам достаточно динамически подгрузить скрипт. Примерно так: https://gomakethings.com/a-better-way-to-load-scri...
  • Как исключить дребезг живого поиска?

    @Interface
    Stalker_RED, нуу в 10 строк укладывается самая простая реализация (которая, впрочем, подойдет в ряде случаев). https://github.com/lodash/lodash/blob/master/debou... ребята из lodash немного вышли за пределы 10 строк :) и последний раз когда я это вдумчиво читал, я не нашел там что-то, что можно выкинуть.

    Насчет моей библиотеки: для решения проблемы в посте не совсем достаточно одного debounce. Он резко улучшит ситуацию, но исправит не все проблемы. Есть 2 потока событий: keydown и получение результата с сервера.

    Обычно запросы исполняются относительно быстро, но чтобы избежать лишней нагрузки на сервер (или не упереться в лимит стороннего сервиса) запрос отсылают не на каждый keydown, а не ранее чем через N мили-секунд после последнего (debounce).

    Однако, это значит, что пользователь не увидит никакого промежуточного результата. Это может быть неудобно. Например, в базе есть товар "Постельное белье розовое с цветочками", и пользователь вбивает прямо ровно эту строку, в таком случае мы могли бы уже на фразе "Постельное бель" вывести ему подсказку и он не стал бы дописывать, а "табнул" бы. Особенно это полезно в случае когда в базе ничего больше "постельного". Поэтому может быть удобно использовать throttle, а не debounce.

    Но можно нарваться на интересную проблему: Порядок отправки запросов и получения ответов может отличаться! То есть: клиент отправит запросы A, B, C, а ответы придут в порядке A, C, B. И если их обработка написана в лоб - то в результате пользователь может увидеть неактуальный ответ B, хотя последнее что но ввел - это C.

    Более того, по схожим причинам, ответы могут не только перемешаться, но и придти все разом одной большой пачкой. (Это актуально и для debounce, только время ответа должно быть больше паузы и пользователь должен успеть отправить второй запрос до исполнения первого). А это уже черевато все тем же "дребезгом". Например, пользователь может вбивать текст в течении 10 секунд, а затем ему разом (с произвольной разницей, например, в 50 мс) вернется ответ на его 5 запросов, в итоге интерфейс моргнет 5 раз за четверть секунды - "дребезг".

    Это значит, что и обработку запроса, надо throttl'ить.

    Точнее обработку throttl'ить нужно, только если вслепую реагировать на все ответы. В то время как обе проблемы (порядок ответов и дребезг при их выводе) можно решить, если реагировать только на актуальный (последний) запрос, а остальные игнорировать.

    На демо-странице можно выставить в последней секции задержку в Fetch time: 500 ± 3000 ms, тогда некоторые запросы будут выполняться дольше, чем более свежие.

    ...так вот библиотеку я и писал для этих целей :)

    - throttle - привычный throttle
    - takeLast - брать в учет только актуальный запрос
    - watchPromise - по пути добавил простую поддержку лоадеров

    Ну и плюс она предоставляет несколько другой АПИ. В случае с обычным debounce, вся функция получается не совсем ассинхронной - она исполнятся синхронно, просто в ряде случаев ничего не делает. В то время как "мой" throttle возвращает функцию которая, возвращает "честный" Promise, который будет разрезолвен, когда будет получен актуальный ответ. Это позволяет выстраивать цепочки .then(...).then и async/await.

    P.s. Вроде бы смысл был в этом :) Писалось 2 года назад, сейчас могу уже что-то путать. :)