Является ли использование async в setTimeout действительным?

У меня была асинхронная функция в Javascript, и я добавил к ней setTimeout. Код выглядит так:

        let timer;
        clearTimeout(timer);
        timer =setTimeout(() => {
        (async() => {
            await this._doSomething();
        })();
        }, 2000);

Цель setTimeout - добавить 2 секунды до запуска функции. Надо быть уверенным, что пользователь перестал печатать.

Должен ли я удалить async/await из этой функции сейчас, так как setTimeout в любом случае асинхронный?

Ответ 1

setTimeout добавляет задержку перед вызовом функции, тогда как async/await является синтаксическим сахаром ontop promises, способ связать код для запуска после вызов завершается, поэтому они разные.

setTimeout имеет ужасные характеристики обработки ошибок, поэтому я рекомендую следующее во всем коде:

let wait = ms => new Promise(resolve => setTimeout(resolve, ms));

а затем никогда больше не вызывайте setTimeout.

Теперь ваш код будет выглядеть следующим образом:

let foo = async () => {
  await wait(2000);
  await this._doSomething();
}

кроме foo ждет завершения doSomething. Обычно это желательно, но без контекста трудно понять, чего вы хотите. Если вы хотите запустить doSomething параллельно с другим кодом, я рекомендую:

async () => { await Promise.all([foo(), this._otherCode()]); };

для объединения и захвата ошибок в одном и том же месте.

Если вы действительно хотели стрелять и забыть _doSomething, а не ждать его, вы можете потерять await, но вы должны попробовать/уловить ошибки:

async () => {
  let spinoff = async () => { try { await foo(); } catch (e) { console.log(e); } };
  spinoff(); // no await!
}

Но я не рекомендую этот шаблон, так как он тонкий и легко пропустить.

Ответ 2

/* contrived example alert */
var foo = 'poo';
function setFoo(callback) (
    setTimeout(function(){
        foo = 'bar';
        callback();
    }, 100);
);
setFoo(function() {
    alert(foo);
});