1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > setTimeout setInterval promise async/await的顺序详解(多种情况 非常详细~)

setTimeout setInterval promise async/await的顺序详解(多种情况 非常详细~)

时间:2019-04-19 22:54:03

相关推荐

setTimeout setInterval promise async/await的顺序详解(多种情况 非常详细~)

本文很长,列举的情况很多。

在阅读本文之前,如果您有充足的时间,请新建一个项目与本文一同实践。

每段代码都有对应的解释,但是自己动手尝试印象才会更深哦~

setInterval:表示多久执行一次,需要clearInterval(timer)来让它停下。要是不clearInterval(timer),它就会越来越快!

setTimeout:表示过了多久之后执行,只会执行一次!

比如这段代码,实现的是每秒都在console里输出现在的时间,5秒后停止。

上代码

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Test</title></head><body><div id="root"></div><script>let timertimer = setInterval(function () {console.log(new Date())}, 1000)setTimeout(function () {clearInterval(timer)}, 5000)</script></body></html>

运行结果:

如果setTimeout设置时间为0呢?

修改一下代码:

<script>let timertimer = setInterval(function () {console.log(new Date())}, 1000)setTimeout(function () {clearInterval(timer)}, 5000)setTimeout(function () {console.log('hello')}, 0)</script>

运行结果:

加上promise

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Test</title></head><body><div id="root"></div><script>console.log('1')setTimeout(() => {console.log('2')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')}, 0)console.log('4')})promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script></body></html>

看下结果:

这一段完全没有调用到。

promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})

为啥呢,因为没有resolve()

加上resolve()之后呢?

<script>console.log('1')setTimeout(() => {console.log('2')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')setTimeout(() => {resolve()}, 0)}, 0)console.log('4')})promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

那是不是什么时候resolve()就什么时候输出呢?

答案是:不是

把“2”换到下面来试一下:

<script>console.log('1')let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')setTimeout(() => {resolve()}, 0)}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

可见3和2的位置确实变了,但是promise部分,就是5和6,仍然是最后出现。

那有多个setTimeout会怎样呢?我们加一个“2.5”试一下:

<script>console.log('1')setTimeout(() => {console.log('2.5')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')setTimeout(() => {resolve()}, 0)}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

输出结果是:

可见是从上至下的啊~

如果让resolve()和console.log(‘3’)摆在一起呢?

<script>console.log('1')setTimeout(() => {console.log('2.5')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')resolve()}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

执行结果:

可见,在setTimeout里套的setTimeout会被最后执行。

如果改一下执行时间呢?把2.5输出的时间改为运行0.1s之后?

<script>console.log('1')setTimeout(() => {console.log('2.5')}, 100)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')setTimeout(() => {resolve()}, 0)}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

执行结果:

它会出现在最后!

那如果resolve()执行时间延后呢?

<script>console.log('1')let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')resolve()}, 100)console.log('4')})setTimeout(() => {console.log('2')}, 0)promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

运行结果:

该先执行的还是先执行了啊~

加上async/await会怎样?神奇的事发生了!

<script>console.log('1')setTimeout(() => {console.log('2.5')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')resolve()}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)async function async1() {console.log('async1 start')await async2()console.log('async1 end')}async function async2() {console.log('async2')}console.log('script start')async1()console.log('script end')promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

输出结果是:

async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再执行函数体内后面的语句。可以理解为,是让出了线程,跳出了 async 函数体。

setTimeout会在async/await之后再执行。但promise的内容会在async/await之前执行。

混乱起来了:把setTimeout塞进async/await中会怎么样?

<script>console.log('1')setTimeout(() => {console.log('2.5')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')resolve()}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)async function async1() {console.log('async1 start')setTimeout(() => {console.log('async1 start setTimeout')}, 0)await async2()console.log('async1 end')setTimeout(() => {console.log('async1 end setTimeout')}, 0)}async function async2() {console.log('async2')setTimeout(() => {console.log('async2 setTimeout')}, 0)setTimeout(() => {console.log('async2 setTimeout after')}, 100)}console.log('script start')async1()console.log('script end')promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script>

输出结果:(看仔细了哦)

所以塞在async/await中的setTimeout会被最后执行。

终极混乱:

let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')setTimeout(() => {resolve()}, 0)}, 0)console.log('4')})

在Promise里的setTimeout里的setTimeout里的resolve()是什么时候执行的?

完整代码:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Test</title></head><body><div id="root"></div><script>console.log('1')setTimeout(() => {console.log('2.5')}, 0)let promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('3')setTimeout(() => {resolve()}, 0)}, 0)console.log('4')})setTimeout(() => {console.log('2')}, 0)async function async1() {console.log('async1 start')setTimeout(() => {console.log('async1 start setTimeout')}, 0)await async2()console.log('async1 end')setTimeout(() => {console.log('async1 end setTimeout')}, 0)}async function async2() {console.log('async2')setTimeout(() => {console.log('async2 setTimeout')}, 0)setTimeout(() => {console.log('async2 setTimeout after')}, 100)}console.log('script start')async1()console.log('script end')promise.then((res) => {console.log('5')}).then((res) => {console.log('6')})console.log('7')</script></body></html>

输出结果:

啊,原来是这样,这一部分会被最后执行!

(作者已经要陷入混乱中了…)

休息一下…接着做~

setTimeout的层叠实验:

<script>setTimeout(() => {console.log('1')setTimeout(() => {console.log('1.2.before3')setTimeout(() => {console.log('1.3.1')}, 0)setTimeout(() => {console.log('1.3.2')}, 0)}, 0)setTimeout(() => {console.log('1.2.after3')}, 0)}, 0)setTimeout(() => {console.log('2')setTimeout(() => {console.log('2.2.1')}, 0)setTimeout(() => {console.log('2.2.2')}, 0)}, 0)setTimeout(() => {console.log('3')}, 0)</script>

输出结果:

事实证明,setTimeout是一层一层来的,理解好“第几批”很重要。

可以自己尝试一下,这个如金字塔一样的结构,先搭好第一层地基,才会向上搭建这种思想。

至此你已经看完了所有的内容,感谢观看,实操大于理解,还是建议读者新建一个项目自己动手尝试各种情况,还有更多嵌套情况本文没有列出,如有勤奋的同学列举,欢迎讨论~

补充:

setTimeout并不是准时的原因

因为 JavaScript 是一个单线程序的解释器,因此一定时间内只能执行一段代码。为了控制要执行的代码,就有一个 JavaScript 任务队列。这些任务会按照将它们添加到队列的顺序执行。setTimeout() 的第二个参数告诉 JavaScript 再过多长时间把当前任务添加到队列中。如果队列是空的,那么添加的代码会立即执行;如果队列不是空的,那么它就要等前面的代码执行完了以后再执行

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。