11-Promise与异步方案
码路教育 6/22/2022
# 1. 最早解决异步
JS中的代码,分两类
- 同步代码
- 我们写的绝大代码都是从上到下执行的,也就是说代码的书写顺序和代码的执行顺序是一样的,这样的代码是同步代码,也就说,你看到的98%的代码都是同步代码。
- 异步代码
- 还有一部分代码,是异步代码,异步代码的书写顺序和代码的执行顺序不一样,这样的代码很少,我们学一类,说一类,前面学的定时器,就是异步代码。
最早解决异步
<script>
// 最早解决异步问题:靠回调函数
// 1.设计这样的一个函数
function execCode(counter, successCallback, failureCallback) {
// 异步任务
setTimeout(() => {
if (counter > 0) { // counter可以计算的情况
let total = 0
for (let i = 0; i < counter; i++) {
total += i
}
// 在某一个时刻只需要回调传入的函数
successCallback(total)
} else { // 失败情况, counter有问题
failureCallback(`${counter}值有问题`)
}
}, 3000)
}
// 2.ES5之前,处理异步的代码都是这样封装
execCode(100, (value) => {
console.log("本次执行成功了:", value)
}, (err) => {
console.log("本次执行失败了:", err)
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 2. Promise介绍
Promise是ES6中的一个类,翻译是承诺,许诺的意思。
- new Promise就可以得到一个对象,new Promise时,需要传入一个回调函数,这个回调函数是立即执行,叫执行器,这个执行器中有两个参数,分别是resolve和reject,在执行器,可以写代码代码,代码如下:
<script>
// p叫promise对象
// 手写promise
// 当new Promise时,执行器会立即执行
// Promise有三个状态 当new出来时,是处于等状态
// 调用resolve可以把等待状态的promise变成成功态
// 调用reject可以把等待状态的promise变成失败态
// 一个promise只能从等待到成功或从等待到失败
let p = new Promise((resolve, reject) => {
console.log("我是执行器,我立即执行了...");
// 在执行器中通常写异步代码
// 我们说的异步指的是定时器中的回调函数
setTimeout(() => {
// console.log("我是定时器");
// 在异步代码中,可以调用resovle或reject
// resolve,reject是一个函数
// resolve中的值,就是成功的值,也就是终值 value
// resolve("包包"); // 就是把等待的promise变成成功的promise
// reject中的值,就是失败的值,也就是失败的原因 reason
reject("没钱"); // 就是把等待的promise变成失败的promise
}, 3000)
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Promise有三种状态:
- 等待状态:pending 默认你创建出来的promise是处于等待状态
- 成功状态:fulfulled 当调用resolve时,就可以把promise从等待变成成功
- 失败状态:rejected 当调用reject时,就可以把promise从等待变成失败
一个函数可以返回一个promise,如下:
<script>
// Promise解决异步问题
function execCode(counter) {
let promise = new Promise((resolve, reject) => {
// 异步任务
setTimeout(() => {
if (counter > 0) { // counter可以计算的情况
let total = 0
for (let i = 0; i < counter; i++) {
total += i
}
// 成功的回调
resolve(total)
} else { // 失败情况, counter有问题
// 失败的回调
reject(`${counter}有问题`)
}
}, 3000)
})
return promise;
}
let promise = execCode(100)
promise.then(result => {
console.log(result);
}, err => {
console.log(err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 3. Promise系统掌握之resolve的实参问题
<script>
// resolve的实参问题
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p的resolve")
reject("没钱")
}, 2000)
})
const promise = new Promise((resolve, reject) => {
// 1)参数是普通的数据
// resolve(["a","b","c"])
// 2)参数是promise
// 如果resolve的参数是promise,最终结果由p决定
// resolve(p)
// 3)参数是thenable(就是一个对象中有一个then函数)
resolve({
then: function(resolve, reject) {
// resolve("包包")
reject("没钱")
}
})
});
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 4. Promise系统掌握之then函数
<script>
// then函数
const promise = new Promise((resolve, reject) => {
resolve("success")
// reject("error")
});
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
})
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
})
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 5. Promise系统掌握之then函数的返回值
then方法是有返回值的,它返回一个新的promise,只要你敢then,就返回一个新的promise。现在我们需要研究新的promsie是成功的还是失败的,新的promise是成功的还是失败的,取决于上一个then做了什么,当上一个then方法中的回调函数在执行时,新promise处于等待状态,当上一个then返回一个结果时,那这个结果就决定了新的promise的状态,情况有下面四种:
- 上一个then返回一个普通的值(包含und) 新的promise是成功的promsie
- 上一个then返回一个promise
- 上一个then返回一个thenable值
- 上一个then抛出一个错误
<script>
// then函数的返回值问题
const promise = new Promise((resolve, reject) => {
resolve("success")
});
// then函数需要返回一个新的promise
promise.then(res => {
console.log(res);
// 这里没有返回值,默认返回und
// 如果返回一个普通值 整体的promise就是一个成功的promise 终值是这个普通值 包括und
// return "hello"
// return 123;
}, err => {
console.log(err);
}).then(res => {
console.log("res:", res);
}, err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script>
const p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("OK~")
reject("BAD~")
}, 2000)
})
// then函数的返回值问题
const promise = new Promise((resolve, reject) => {
resolve("success")
});
promise.then(res => {
console.log(res);
// 如果返回的是一个promise,整体promise的结果取决于你返回的promise的状态
return p;
}, err => {
console.log(err);
}).then(res => {
console.log("res:", res);
}, err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script>
// then函数的返回值问题
const promise = new Promise((resolve, reject) => {
resolve("success")
});
promise.then(res => {
console.log(res);
// 如果返回thenable,整体的promise取决于thenable的状态
return {
then: function(resolve, reject) {
// resolve("包包")
reject("没钱")
}
};
}, err => {
console.log(err);
}).then(res => {
console.log("res:", res);
}, err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 6. Promise系统掌握之then的顺延
<script>
// then的顺延
const promise = new Promise((resolve, reject) => {
resolve("success")
});
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
}).then(null, err => {
console.log("err:", err);
}).then(res => {
console.log("res:", res);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script>
// then的顺延
const promise = new Promise((resolve, reject) => {
reject("bad")
});
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
// 这里返回了und 就意味着新的promise是成功的
// new Error("我错了") 就意味着新的promise是失败的
throw new Error("我错了")
}).then(res => {
console.log("res:", res);
}, null).then(null, err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
// then的顺延
const promise = new Promise((resolve, reject) => {
reject("bad")
});
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
throw new Error("我错了")
}).then(res => {
console.log("res:", res);
}).catch(err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 7. Promise系统掌握之finally
在ES9中,新增了finally方法,无论promise是成功的,还是失败的,最终都会执行finally
- 代码如下:
<script>
// finally
const promise = new Promise((resolve, reject) => {
reject("bad")
});
promise.then(res => {
console.log(res);
}, err => {
console.log(err);
throw new Error("我错了")
}).then(res => {
console.log("res:", res);
}).catch(err => {
console.log("err:", err);
}).finally(() => {
console.log("哈哈哈哈")
console.log("呵呵呵呵")
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 8. Promise系统掌握之类方法(静态方法)
前面学习的then,catch,finally都是promise实例上的方法,其实在Promise这个类上面,还有一些,这些方法,叫静态方法,代码如下:
<script>
// 类方法(静态方法)
const promise = Promise.resolve("hello")
promise.then(res => {
console.log("then结果:", res)
})
// 相当于
// new Promise((resolve) => {
// resolve("hello")
// })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<script>
// 类方法(静态方法)
const promise = Promise.reject("rejected error")
promise.catch(err => {
console.log("err:", err)
})
// 相当于
// new Promise((_, reject) => {
// reject("rejected error")
// })
</script>
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<script>
// 类方法(静态方法) all
// 创建三个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p1 resolve")
reject("p1 reject error")
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p2 resolve")
reject("p2 reject error")
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p3 resolve")
}, 5000)
})
// 类方法(静态方法) all
// all的作用:所有promise都成功后,得到所有成功后的promise结果
// 如果有一个先失败了,直接得到最先失败promise的结果
Promise.all([p1, p2, p3]).then(res => {
// ['p1 resolve', 'p2 resolve', 'p3 resolve']
console.log(res);
}).catch(err => {
console.log(err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script>
// 类方法(静态方法) allSettled
// 创建三个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p1 resolve")
reject("p1 reject error")
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p2 resolve")
reject("p2 reject error")
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p3 resolve")
}, 5000)
})
// 类方法: allSettled
// [
// {
// "status": "fulfilled",
// "value": "p1 resolve"
// },
// {
// "status": "fulfilled",
// "value": "p2 resolve"
// },
// {
// "status": "fulfilled",
// "value": "p3 resolve"
// }
// ]
// allSettled 获取所有的promise的结果,不管成功还是失败
Promise.allSettled([p1, p2, p3]).then(res => {
console.log("all settled:", res)
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<script>
// 创建三个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p1 resolve")
reject("p1 reject error")
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p2 resolve")
reject("p2 reject error")
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p3 resolve")
}, 5000)
})
// 类方法: race方法 race是比赛的意思
// 特点: 会等到第一个Promise有结果(无论这个结果是fulfilled还是rejected)
Promise.race([p1, p2, p3]).then(res => {
console.log("race promise:", res)
}).catch(err => {
console.log("race promise err:", err)
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<script>
// 类方法: any方法
// 创建三个Promise
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p1 resolve")
reject("p1 reject error")
}, 3000)
})
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("p2 resolve")
// reject("p2 reject error")
}, 2000)
})
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("p3 resolve")
reject("p3 reject error")
}, 5000)
})
// 类方法: any方法
// any 返回第1个成功的 或者 返回所有都失败了
Promise.any([p1, p2, p3]).then(res => {
console.log("any promise res:", res)
}).catch(err => {
console.log("any promise err:", err)
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 9. 认识async函数
async是一个关键字,用于声明一个异步函数,async是asynchronous简写,是异步的意思。
sync是synchronous简写,是同步的意思。
<script>
// 普通函数
// function foo() { }
// const bar = function () { }
// const baz = () => { }
// 生成器函数
// function* foo() { }
// 异步函数
async function foo() {
console.log("foo function1")
console.log("foo function2")
console.log("foo function3")
}
// async返回promise
let res = foo();
console.log(res);
let gn = async function() {};
let kn = async () => {};
class Person {
async running() {}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 10. async函数的返回值
异步函数的结果永远都是promise
异步函数内部代码的执行过程和普通函数是一样的,默认也是同步执行。异步函数和普通函数的区别,如下:
- 异步函数可以有返回值,但是不管返回什么普通值,都会包裹在Pormise.resolve中
- 如果异步函数自己返回了promise,得到的Promies状态由这个promise决定
- 如果我们异步函数返回值是一个对象并且实现thenable,得到的Promies状态由then方法中做了什么才能决定
- 如果在async函数中抛出一个错误,得到的promise是一个失败的promsie
<script>
async function foo() {
console.log("foo function1")
console.log("foo function2")
console.log("foo function3")
// 1)返回普通值,promis是成功的promsie
// return 123;
// 2)返回promise res这个promise是成功还是失败,取决于你返回的promise是成功还是失败
// return new Promise((resolve, reject)=>{
// setTimeout(()=>{
// resolve("hello")
// },2000)
// })
// 3)返回thenable res这个promise是成功还是失败,取决于你返回的thenable是成功还是失败
return {
then: function(resolve, reject) {
reject("没钱~")
}
}
}
let res = foo();
res.then(res => {
console.log("res:", res);
}).catch(err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 11. async函数有异常
<script>
// 在async函数中,如果抛出一个错误,res这个promise是失败的promise
async function foo() {
console.log("foo function1")
console.log("foo function2")
console.log("foo function3")
throw new Error("我是异常")
}
let res = foo();
res.then(res => {
console.log("res:", res);
}).catch(err => {
console.log("err:", err);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 12. awati的使用
async关键字可以单独使用,在异步函数内部可以使用await关键字,但是在普通函数中不能使用await关键字,await关键字有什么作用?
- await后面跟一个表达式,这个表达式普通是一个promise
- 这个await可以等待它后面的promise成功后,拿到成功的结果,得到之后,才会执行后面的代码。
await后面跟不同的数据:
- 如果await后面跟一个普通值,那么会直接返回这个值。
- 如果await后面跟一个thenable对象,那么要看你这个thenable中的then做了什么。
- 如果await后面的promise是失败的,需要通过try catch来获取失败的结果。
<script>
// await后面跟一个普通值
// function fn(){
// await 123
// }
// SyntaxError: await is only valid in async functions and the top level bodies of modules
// fn();
// awati 1)必须写在async函数中 2)await后面通常是跟一个promsie
// 3)await前面就可以获取promise成功的结果
async function gn() {
let rs = await 123
console.log("rs:", rs); // 123
// 返回一个und
}
gn().then(res => {
console.log("res:", res);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 13. await后面通常跟promise
<script>
function bar() {
console.log("bar function")
return new Promise(resolve => {
setTimeout(() => {
resolve(123)
}, 2000)
})
}
async function foo() {
// await后续返回一个Promise, 那么会等待Promise有结果之后, 才会继续执行后续的代码
// await下面的代码相当于一个.then
const res1 = await bar()
console.log("await后面的代码:", res1)
const res2 = await bar()
console.log("await后面的代码:", res2)
}
foo()
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 14. 使用async+await处理异常问题
<script>
function requestData(url) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(url)
// reject("error message")
}, 2000);
})
}
async function getData() {
const res1 = await requestData("001")
console.log("res1:", res1)
const res2 = await requestData(res1)
console.log("res2:", res2)
const res3 = await requestData(res2)
console.log("res3:", res3)
return res3
}
getData().then(res => {
console.log(res);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 15. 说一下,什么是浏览器事件环
进程:
- 计算机已经运行直来的程序,是操作系统操作程序的一种方式。当一个软件运行起来后,就是一个进程,电脑上可以运行很多软件,在OS上,有很多的进程,进程是OS分配资源(CPU和内存)的基本单位。OS可以当在一个工厂,一个个的车间就是进程。
线程:
- 操作系统能够运行运算调度的最小单位,一个进程中,至少要包含一个线程,用来执行程序中的代码,这个线程叫主线程,线程才是真正干活的,类似于工厂中的工人。一个车间如果只有一个工人,就是单线程,如果一个车间中有N个工人,就是多线程。
浏览器是多进程的:
- 浏览器是一个多进程的软件,一个选项卡,就是一个进程,进程之间一般是独立的。在每一个进程中,包含了很多的线程,其中就包括JS代码执行线程。执行JS代码的线程就一个,也就是说,同一个时刻,只能做一件事,那么我们就说JS是单线程的。如果遇到了一个非常耗时的任务,线程就阻塞,此时,JS的主线程不会等待,浏览器会开一些其它线程去执行耗时任务,小线程执行的结果,就通过回调函数告诉主线程,我们说的JS是单线程的,是指主线程是单线程的,浏览器内部还可以开一些其它线程,如定时器线程,如ajax数据请求线程。
异步代码分两类:
- 宏任务:ajax,setTimeout,setInterval,DOM事件监听,UI渲染....
- 微任务:promies中的then回调 Mutaion Observer ...
JS代码的执行顺序:
- 从代码段开始执行
- 如果遇到一个宏任务,会把这个任务放到一个宏任务队列,如果遇到一个微任务,就把这个微任务放到微任务任务中。
- 当同步代码执行完毕后,先去清空微任务队列。
- 当微任务队列清空完毕后,从宏任务队列中取出一个宏任务,去执行,在执行过程中,你的宏任务中可能还有同步代码或宏任务或微任务,重复上面的步骤,执行完一个宏任务,肯定要清空微任务队列。
# 16. 事件环相关的面试题
<script>
console.log(1)
setTimeout(() => {
console.log(2)
Promise.resolve().then(() => {
console.log(3)
})
})
setTimeout(() => {
console.log(4)
Promise.resolve().then(() => {
console.log(5)
})
})
Promise.resolve().then(() => {
console.log(6)
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(function() {
console.log('promise1');
})
.then(function() {
console.log('promise2');
});
console.log('script end');
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
setTimeout(function() {
console.log("setTimeout1");
new Promise(function(resolve) {
resolve();
}).then(function() {
new Promise(function(resolve) {
resolve();
}).then(function() {
console.log("then4");
});
console.log("then2");
});
});
new Promise(function(resolve) {
console.log("promise1");
resolve();
}).then(function() {
console.log("then1");
});
setTimeout(function() {
console.log("setTimeout2");
});
console.log(2);
new Promise(function(resolve) {
resolve();
}).then(function() {
console.log("then3");
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<script>
async function bar() {
console.log("22222")
return new Promise((resolve) => {
resolve()
})
}
async function foo() {
console.log("111111")
await bar()
console.log("33333")
}
foo()
console.log("444444")
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script>
async function async1() {
console.log('async1 start')
await async2();
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function() {
console.log('setTimeout')
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1')
resolve();
}).then(function() {
console.log('promise2')
})
console.log('script end')
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<script>
Promise.resolve().then(() => {
console.log(0);
return 4
}).then((res) => {
console.log(res)
})
Promise.resolve().then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).then(() => {
console.log(3);
}).then(() => {
console.log(5);
}).then(() => {
console.log(6);
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script>
let start = Date.now();
for (let i = 0; i < 10000000000; i++) {}
console.log("哈哈")
let end = Date.now();
console.log((end - start) / 1000);
setTimeout(() => {
console.log("111")
}, 10000);
let start1 = Date.now();
for (let i = 0; i < 10000000000; i++) {}
console.log("呵呵")
let end1 = Date.now();
console.log((end1 - start1) / 1000);
// while(true){}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19