js知识点-异步编程

1. 异步编程
同步:同一时间只能做一件事
异步:同一时间做多件事
1.2 JS中的异步实现:单线程非阻塞式
JS单线程:不是只js引擎只有一个线程。运行代码只有一个线程,但是还有其他线程来执行其他代码。
例如:时间函数的计时,AJAX技术中的和后台交互等
注意:由于执行代码只有一个线程,所以同步代码中出现死循环,后续同步代码以及异步的回调函数都无法执行

1
2
3
4
5
6
7
console.log("start");
setTimeout(function(){
console.log("timeout");
},5000);
console.log("end");
// start end 等待5秒 timeout
// setTimeout方法,放入队列中

2. ES6:Promise实现异步
参数:Promise构造函数接收一个回调函数,回调函数接收两个参数resolve,reject,通过Promise对象的then方法实现异步
Promise的作用:避免回调地狱
2.1 reject是出现错误时调用的方法,触发catch中的回调函数

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
let pm = new Promise(function(resolve,reject){
console.log("异步开始");
resolve()
//dosomething
});
console.log("go on");
pm.then(function(){
console.log("异步完成");
});
// 1.异步开始 2.go on 3.异步完成
// then方法将内容放入队列

// 调用resolve可以把数据传递给then的回调函数
let err = true
let pm = new Promise(function(resolve,reject){
if(!err){
resolve("this is data");
}else{
reject("fail")
}

});
console.log("go on");
pm.then(function(data){
console.log("异步完成",data);
});
pm.catch(function(err){
console.log("出现错误",err);
});

2.2 封装Promise,避免多次创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let timeout = function(time){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve();
},time);
});
}
console.log("go on");
timeout(2000).then(function(){
console.log("first");
return timeout(2000);
}).then(function(){
console.log("second");
return timeout(2000);
}).then(function(){
console.log("third");
return timeout(2000);
}).then(function(){
console.log("fourth");
return timeout(2000);
});

3.生成器和迭代器
3.1 迭代器
迭代器:提供统一的遍历数据的方式,只要在遍历的数据结构中添加一个支持迭代器的属性:[Symbol.iterator]
默认支持迭代器的结构【for of循环】:Array、Map、Set、String、TypedArray、函数的arguments对象、NodeList对象

1
2
3
4
5
6
let ary = [1,2,3];
let it = ary[Symbol.iterator](); // ឴ݐහᕟӾጱᬽդ࢏
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }

迭代器遍历对象【for in 更好点】

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
let obj = {
name: 'xiejie',
age: 18,
gender: '男',
intro: function () {
console.log('my name is ' + this.name);
},
[Symbol.iterator]: function () {
let i = 0;
let keys = Object.keys(this); // 获取当前对象的所有属性形成一个数组
return {
next: function () {
return {
value: keys[i++], // 外部每次执行next都能得到数组中的第i个元素
done: i > keys.length // 数组数据遍历完返回true
}
}
}
}
}
for (let attr of obj) {
console.log(attr+ ' '+obj[attr]);
}
// let it = obj[Symbol.iterator]();
// console.log(it.next()); // { value: 'name', done: false }
// console.log(it.next()); // { value: 'age', done: false }
// console.log(it.next()); // { value: 'gender', done: false }
// console.log(it.next()); // { value: 'intro', done: false }
// console.log(it.next()); // { value: undefined, done: true }

3.2 生成器
写法:在声名函数时加在function关键词后面
function* say(){} const say = function*(){}
生成器函数和普通函数的区别:
1.普通函数在调用后,必然开始执行函数,直到执行完成或者return,中途不暂停
2.生成器函数可以通过【yield关键字】将函数挂起,或者理解为暂停,外部通过调用next方法,让函数继续执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function* say(){
yield "开始";
yield "执行中";
yield "结束"; }
let it = say(); // 调用say函数,得到迭代器
for(let i of it){
console.log(i)
}

console.log(it.next()); // { value: '开始', done: false }
console.log(it.next()); // { value: '执行中', done: false }
console.log(it.next()); // { value: '结束', done: false }
console.log(it.next()); // { value: undefined, done: true }

生成器实现异步操作

1
2
3
4
5
6
7
8
9
function* delay() {
yield new Promise((resolve, reject) => { setTimeout(() => { resolve() },
1) })
console.log("go on");
}
let it = delay(); // 得到迭代器
it.next().value.then(() => {
it.next();
});

4. ES7:async和await
async函数处理异步,实际上只是生成器的语法糖
async执行顺序:先执行同步代码,然后通过执行器来执行async里的代码,有返回值在外部通过then()方法的回调函数来接收
await后面必须是一个Promise对象【因为promise对象会返回给外部执行器,并在异步完成后执行resolve】
如果await后面不是Promise对象,await会把他包装成一个Promise对象
通过关键字async,外部产生了相应的执行器来执行,在异步操作完成后执行回调函数

1
2
3
4
5
async function delay(){
await new Promise((resolve) => {setTimeout(()=>{resolve()},2000)});
console.log("go on);
}
delay();

// 箭头函数写在参数前面 const delay = async () => {}
执行步骤
2.获取async函数的返回结果实际是return出来的promise对象

1
2
3
4
5
6
7
8
9
10
// 得到返回的具体内容
const delay = async () => {
await new Promise((resolve) => {setTimeout(()=>{ console.log("123"); resolve()},2000)});
return "finish";
}
let result = delay();
console.log(result);
result.then(function(data){
console.log("data:",data);
});

多个异步操作进行

1
2
3
4
5
6
7
8
9
10
11
12
function time(ms){
return new Promise((resolve,reject) => {
setTimeout(()=>{resolve()},ms);
});
}
const delay = async () => {
await time(2000);
console.log("t1 finish");
await time(2000);;
console.log("t2 finish");
}
delay()

-------------本文结束感谢您的阅读-------------

我的传送门:个人网站GithubGitee