是否需要setTimeout? [英] Is setTimeout required?

查看:75
本文介绍了是否需要setTimeout?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个async,await和setTimeout()的问题。
我想,我使用异步函数来处理慢进程。所以我尝试了一个大循环。在我的计算机上,运行以下代码需要几秒钟:

  function slowFunction(){
return new Promise (resolve => {
setTimeout(()=> {
for(let i = 0; i< 4000000000; i ++){};
resolve('ready at'+ new Date()。toLocaleTimeString('de'));
},0);
});
};


console.log('开始:'+新日期()。toLocaleTimeString('de'));

(async()=> {
console.log('调用慢速函数。');
console.log(等待slowFunction());
})();

console.log('无需等待慢速函数:'+ new Date()。toLocaleTimeString('de'));

输出为:

 开始时间:16:39:20 
调用慢速函数。
没有必要等待慢功能:16:39:20
准备好16:39:23

现在的问题是:下一个代码有什么区别:

  function slowFunction (){
返回新的Promise(resolve => {
for(let i = 0; i< 4000000000; i ++){};
resolve('ready at'+ new date ()。toLocaleTimeString('de'));
});
};

console.log('开始:'+新日期()。toLocaleTimeString('de'));

(async()=> {
console.log('调用慢速函数。');
console.log(等待slowFunction());
})();

console.log('无需等待慢速函数:'+ new Date()。toLocaleTimeString('de'));

输出为:

 开始时间:16:39:20 
调用慢速函数。
没有必要等待慢功能:16:39:23
准备好16:39:23

在第一个例子中,它看起来像是异步的。通过第二个例子,函数等待循环结束。



我是否必须使用setTimeout或我在代码中有错误或者我错了?在这两种情况下,解析语句都在大循环之后。



async和await的大多数示例都使用了setTimeout,但我想,这只是为了模拟一个中断。 / p>

感谢您提前的帮助。



最佳迎接
Pascal

解决方案

TL:DR



承诺和 async 函数不会将代码卸载到另一个线程。如果你想将这个长时间运行的进程从主线程移开,在浏览器上查看网络工作者,并在Node.js上查看子进程



详细信息



Promises和 async 函数(这只是创建和创建的语法)使用promises)不要将你的处理移动到任何其他线程,它仍然发生在你​​开始进程的同一个线程上。他们所做的唯一事情是确保然后 catch 回调被异步调用。它们不会使您的代码异步(除了那一件事,确保回调异步发生)。



所以你的第一个块使用 setTimeout 只是设置超时,返回一个promise,然后当超时到期时,它会在你的慢速运行进程执行时阻塞主线程。这只是在阻塞发生一点点时发生变化,它不会改变阻塞的事实。



你可以在这里看到效果,注意计数器暂停时的效果长时间运行的过程发生:



  function slowFunction( ){return new Promise(resolve => {setTimeout(()=> {const stop = Date.now()+ 2000; while(Date.now()< stop){//忙等待(显然,从不真的这样做)}},1000);});}; console.log(在slowFunction之前); slowFunction()。then(()=> {console.log(然后在slowFunction的承诺上处理); } .catch(console.error); console.log(after slowFunction之后); let counter = 0; const timer = setInterval(()=> {console.log(++ counter);},100); setTimeout(()=> {clearInterval(时间r); console.log(done);},3000);  

  .as-console-wrapper {max-height:100%!important;}  



你的第二个块没有使用 setTimeout 只是立即阻止,因为promise执行函数(你传递的函数 new Promise )立即同步运行,你没有做任何让它异步的事情。



你可以在这里看到;计数器立即暂停,而不是稍后:



  function slowFunction(){return new Promise(resolve => {const stop = Date.now()+ 2000; while(Date.now()< stop){//忙等待(显然,从未真正这样做)}} );;; console.log(在slowFunction之前); slowFunction()。then(()=> {console.log(然后在slowFunction的承诺上处理);})。catch(console.error); console .log(after slowFunction之后);让counter = 0; const timer = setInterval(()=> {console.log(++ counter);},100); setTimeout(()=> {clearInterval(timer) ); console.log(done);},3000);  

  .as-console-wrapper {max-height:100%!important;}  



我们不是ev在慢速运行日志之前看到,直到长时间运行的代码完成之后,因为浏览器永远没有机会重新绘制,我们让线程陷入困境。



关于 async 函数: async 函数中的代码开始同步,并且是同步的,直到第一个等待(或其他构造,例如 setTimeout ,它安排事情稍后执行)。只有那之后的代码是异步的(因为它必须等待)。



这是一个证明:



  async function foo(){console.log(before await);等待Promise.resolve(); console.log(after await);} console.log(在foo之前); foo()。then(()=> {console.log(然后处理foo的承诺);})。catch (console.error); console.log(after foo);  



以下是其输出:

 $ f $ b之前foo 
之前等待
之后foo
之后等待
然后处理foo的承诺

注意在等待之前发生在之前foo之后;它与 foo 的调用同步。但是等待之后直到稍后才发生(因为 await Promise.resolve()必须使其后面的代码异步发生;它的语法然后的糖,即使承诺已经解决,也承诺不会同步调用其处理程序。)


I have a question to async, await and setTimeout(). I thought, I use asynchron functions for slow processes. So I tried it with a large loop. On my Computer, it needs few seconds to run the following code:

function slowFunction() {
    return new Promise(resolve => {
        setTimeout(() => {
            for (let i = 0; i < 4000000000; i++) {};
            resolve('Ready at ' + new Date().toLocaleTimeString('de'));
        }, 0);
    });
};


console.log('Start: ' + new Date().toLocaleTimeString('de'));

(async () => {
    console.log('Call slow function.');
    console.log(await slowFunction());
})();

console.log('There is no need to wait for the slow function: ' + new Date().toLocaleTimeString('de'));

The output is:

Start: 16:39:20
Call slow function.
There is no need to wait for the slow function: 16:39:20
Ready at 16:39:23

And now the question: What is the difference to the next code:

function slowFunction() {
    return new Promise(resolve => {
        for (let i = 0; i < 4000000000; i++) {};
        resolve('Ready at ' + new Date().toLocaleTimeString('de'));
    });
};

console.log('Start: ' + new Date().toLocaleTimeString('de'));

(async () => {
    console.log('Call slow function.');
    console.log(await slowFunction());
})();

console.log('There is no need to wait for the slow function: ' + new Date().toLocaleTimeString('de'));

The output is:

Start: 16:39:20
Call slow function.
There is no need to wait for the slow function: 16:39:23
Ready at 16:39:23

By the first example, it looks like asynchron. By the second example, the function wait for the end of loop.

Do I have to use setTimeout or do I have an error in the code or am I getting it wrong? I both cases, the resolve statment is behind the large loop.

The most examples for async and await used setTimeout, but I think, it's just to simulate a break.

Thanks for your help in advance.

Best greets Pascal

解决方案

TL:DR

Promises and async functions don't offload your code to another thread. If you want to move that long-running process off the main thread, on browsers look at web workers, and on Node.js look at child processes.

Details

Promises and async functions (which are just a syntax for creating and consuming promises) don't move your processing to any other thread, it still happens on the same thread you start the process on. The only thing they do is ensure that then and catch callbacks are called asynchronously. They don't make your code asynchronous (other than that one thing, ensuring the callbacks happen asynchronously).

So your first block using setTimeout just sets a timeout, returns a promise, and then when the timeout expires it blocks the main thread while your slow-running process executes. This just changes when the blocking happens a little bit, it doesn't change the fact of the blocking.

You can see that effect here, notice how the counter pauses when the long-running process occurs:

function slowFunction() {
  return new Promise(resolve => {
    setTimeout(() => {
      const stop = Date.now() + 2000;
      while (Date.now() < stop) {
        // busy wait (obviously, never really do this)
      }
    }, 1000);
  });
};

console.log("before slowFunction");
slowFunction()
  .then(() => {
    console.log("then handler on slowFunction's promise");
  })
  .catch(console.error);
console.log("after slowFunction");

let counter = 0;
const timer = setInterval(() => {
  console.log(++counter);
}, 100);
setTimeout(() => {
  clearInterval(timer);
  console.log("done");
}, 3000);

.as-console-wrapper {
  max-height: 100% !important;
}

Your second block not using setTimeout just blocks right away, because the promise executor function (the function you pass new Promise) runs immediately and synchronously, and you're not doing anything to make it asynchronous.

You can see that here; the counter pauses right away, not later:

function slowFunction() {
  return new Promise(resolve => {
    const stop = Date.now() + 2000;
    while (Date.now() < stop) {
      // busy wait (obviously, never really do this)
    }
  });
};

console.log("before slowFunction");
slowFunction()
  .then(() => {
    console.log("then handler on slowFunction's promise");
  })
  .catch(console.error);
console.log("after slowFunction");

let counter = 0;
const timer = setInterval(() => {
  console.log(++counter);
}, 100);
setTimeout(() => {
  clearInterval(timer);
  console.log("done");
}, 3000);

.as-console-wrapper {
  max-height: 100% !important;
}

We don't even see the before slowFunction log appear until after the long-running code has finished, because the browser never got a chance to repaint, we had the thread hogged.

Regarding async functions: The code in an async function starts out synchronous, and is synchronous until the first await (or other construct, such as setTimeout, that schedules things to execute later). Only the code after that is asynchronous (because it had to wait).

Here's an example demonstrating that:

async function foo() {
  console.log("before await");
  await Promise.resolve();
  console.log("after await");
}

console.log("before foo");
foo()
  .then(() => {
    console.log("then handler on foo's promise");
  })
  .catch(console.error);
console.log("after foo");

Here's the output of that:

before foo
before await
after foo
after await
then handler on foo's promise

Notice how before await occurs before after foo; it's synchronous with the call to foo. But then after await doesn't occur until later (because await Promise.resolve() has to make the code following it occur asynchronously; it's syntactic sugar for then, which promises not to call its handler synchronously even if the promise is already resolved).

这篇关于是否需要setTimeout?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆