在 setTimeout 中使用异步是不是有效?

Posted

技术标签:

【中文标题】在 setTimeout 中使用异步是不是有效?【英文标题】:Is using async in setTimeout valid?在 setTimeout 中使用异步是否有效? 【发布时间】:2016-12-22 20:13:32 【问题描述】:

我在 javascript 中有一个异步函数,并在其中添加了 setTimeout。代码如下:

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

setTimeout 的目的是在函数运行前增加 2 秒。这是为了确保用户停止打字。

我现在应该从这个函数中删除 async/await 吗,因为 setTimeout 无论如何都是异步的?

【问题讨论】:

“代码看起来像那样” 不太可能,这就是为什么你不应该删除 asyncawait。在这个例子中它没有意义,但这并不意味着它在实际代码中没有意义。 有点不清楚你到底在问什么。 supposed 的代码是如何工作的,删除 asyncawait 会如何改变?如果没有一个明确的问题有一个实际的答案,你只会得到非常广泛和固执己见的建议。 我已经编辑了问题,以更清楚地说明我想要达到的目标。 【参考方案1】:
/* contrived example alert */
var foo = 'poo';
function setFoo(callback) (
    setTimeout(function()
        foo = 'bar';
        callback();
    , 100);
);
setFoo(function() 
    alert(foo);
);

【讨论】:

我看到了downvotes,但没有看到cmets,所以要澄清downvotes...这如何回答这个问题?而且你甚至没有使用async 函数,这就是这个问题所要问的。 是的,你显然从这个关于类似主题的更有用的答案中撕下了那个 sn-p...***.com/a/19626821/1580234【参考方案2】:

setTimeout 在函数调用之前添加了一个延迟,而async/await 是承诺之上的语法糖,是一种链接代码运行的方式调用完成后,它们是不同的。

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!

但我不推荐这种模式,因为它很微妙,很容易错过。

【讨论】:

以上是关于在 setTimeout 中使用异步是不是有效?的主要内容,如果未能解决你的问题,请参考以下文章

javascript真的是异步的吗?且看setTimeout的实现原理以及setTimeout的使用场景

js同步异步执行顺序setTimeOut面试题分析

使用 setTimeout 连续异步/等待 [重复]

TypeScript:用于在 setTimeout() 中返回异步函数调用的类型?

setTimeout 和 setInterval

JS异步执行之setTimeout 0的妙用