1 Promise对象
1.1 定义
promise是一种异步编程
解决方案,Promise是一个容器,保存着将来才会执行的代码;从语法角度来说Promise是一个对象,可以用来获取异步操作的消息。
异步操作,同步解决,避免了层层嵌套的回调函数。
1.2 特点
Promise 对象代表一个异步操作,有三种状态:
pending(进行中)、fulfilled(已成功)、rejected(已失败)
状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
Promise 对象的状态改变,只有两种可能:从pending变为fulfilled
和从pending变为rejected
。只要这两种情况发生,状态就凝固不会再变了
,会一直保持这个结果,最后就返回 resolved(已定型
)结果。
1.2 实例化和实例方法
(1) 实例化
Promise 构造函数接收一个函数作为参数,也就是回调函数;该函数有两个参数,分别是resolve和reject。resolve作为成功的回调函数,reject作为失败的回调函数。
(2) 实例方法:
定义在 Promise.prototype 中的方法,通过 Promise 的实例可以直接调用。
.then()
状态由pending=>fulfilled的时候(异步操作成功之后)执行该回调函数
参数: 回调函数,回调函数的参数为resolve函数传递过来的值
返回值: 返回一个新的Promise实例对象,因此可以使用链式调用.catch()
状态由pending=>rejected的时候(异步操作失败之后)执行该回调函数
参数: 回调函数,回调函数的参数为reject函数传递过来的值
返回值: 返回一个新的Promise实例对象,因此可以使用链式调用.finally()
无论异步操作执行成功失败与否,都会执行该回调
参数: 回调函数(回调函数没有参数)
返回值: 返回一个新的Promise实例对象
// 1.创建promise对象
let p1=new Promise(function(resolve,reject){
//非异步 假设异步操作执行成功,修改promise对象状态为成功状态
if(1>0){
resolve("成功");
}else{
reject("失败");
}
})
//在promise原型里有then和catch
// 1.then方法表示的是成功之后的回调,对应resolve
// 2.catch方法表示的是失败之后的回调,对应reject
p1.then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err);
})
//成功
let p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
let data='用户的数据';
resolve(data); //调用resolve之后,对象状态变为成功
// reject('数据读取失败');
},1000);
})
//then()如果有两个参数,第一个参数表示成功的回调,第二个表示失败的回调
//分别代表resolve()和reject()
p2.then((res)=>{
console.log(res,'成功');
},(err)=>{
console.log(err,'失败');
})
promise 是一个构造函数,下面来简单手写一个 promise:
let promise = new Promise((resolve,reject)=>{
if(res){
resolve(res);
}else{
reject(err);
}
})
promise.then((res)=>{
console.log(res);
}).catch((err)=>{
console.log(err)
})
(3) 静态方法
定义在Promise中的方法,通过Promise可以直接调用。
//考虑到可能有多个请求需要发送,需要创建多个承诺对象,所以采用工厂函数进行封装
function getPromise(url,method='get',data=null){
return new Promise((resolve,reject)=>{
$.ajax({
url:url,
method:method,
data:data,
success(res){
resolve(res)
},
error(err){
reject(err)
}
})
})
}
let p1=getPromise('url');
let p2=getPromise('url');
// p1.then((res)=>{
// console.log(res,'1111111')
// })
// p2.then((res)=>{
// console.log(res,'222222')
// })
// all 只有两个异步操作请求都成功才会返回成功的结果,否则返回失败对象
// race 谁的响应先拿到用谁的结果 无论成功与否
//any 有成功用成功的,都失败就失败
let p=Promise.any([p1,p2]);
p.then((res)=>{
console.log(res)
}).catch((err)=>{
console.log(err)
})
2 迭代器
2.1 定义
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口(对象中的一个属性),就可以完成遍历操作。
原生具备iterator接口的数据(可用for of遍历):
Array , Arguments , Set , Map , String , TypedArray , NodeList
2.2 Iterator的作用:
1)为各种数据结构,提供一个统一的、简便的访问接口
2)使得数据结构的成员能够按某种次序排列
3)ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费
2.3 遍历过程:
1)创建一个指针对象,指向当前数据结构的起始位置。遍历器对象本质上就是一个指针对象。
2) 第一次调用指针对象的next()方法,可以将指针指向数据结构的第一个成员。
3)接下来不断调用next()方法,指针一直往后移动,直到指向最后一个成员
4)每调用next()方法返回一个包含value和done属性的对象
let arr1=['tom','vicky','jacky'];
let values=arr1.values();
console.log(values.next()); //{ value: 'tom', done: false }
console.log(values.next()); //{ value: 'vicky', done: false }
console.log(values.next()); //{ value: 'jacky', done: false }
console.log(values.next()); //{ value: undefined, done: true }
//done属性是一个布尔值,表示是否遍历结束,false表示还没有结束,true表示结束
3 Generator 函数
3.1 简介
Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同;简单的把Generator 理解为一个状态机,封装了多个内部状态。执行Generator 函数会返回一个迭代器对象,可以通过调用迭代器next依次遍历Generator函数内部的每一个状态。
3.2 特征
1)function关键字与函数名之间有个星号
2)函数内部使用yield表达式
//1.创建Generator函数 每个状态之间都是独立的,运行都是互不干扰的
function* myGenFun(){
console.log('状态一');
yield 'hello';
console.log('状态二');
yield 'world';
console.log('状态三');
return 'ending'; //return标志该函数的结束
}
let result=myGenFun();
console.log(result);//返回的是一个Generator对象,也是一个迭代器对象
console.log(result.next());
console.log(result.next());
console.log(result.next());
//打印结果:
//Object [Generator] {}
//状态一
//{ value: 'hello', done: false }
//状态二
//{ value: 'world', done: false }
//状态三
//{ value: 'ending', done: true }
上面的代码有三个状态:‘hello’ ‘world’ ‘ending’
Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个迭代器对象,调用遍历器对象的next方法,使得指针移向下一个状态。
每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。也就是说,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
上面的代码一共调用了四次next方法:
next()第一次调用
:Generator 函数开始执行,直到遇到第一个yield表达式为止。next方法返回一个对象,它的value属性就是当前yield表达式的值hello,done属性的值false,表示遍历还没有结束。
next()第二次调用
:Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。next方法返回的对象的value属性就是当前yield表达式的值world,done属性的值false,表示遍历还没有结束。
next()第三次调用
:Generator 函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束),next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined);此时done为ture,表示遍历结束。
3.3 参数
在generator函数中可以传递参数,next()方法可以传入实参,这个实参就是前一个yield语句的整体返回结果
function* gen(arg){
console.log(arg);
let one=yield 111;
console.log(one);
let two=yield 222;
console.log(two);
let three=yield 333;
console.log(three);
}
let result=gen('hello world');
result.next(); //hello world 执行到第一个yield
result.next('AAA'); //AAA 执行到第二个yield,传递的实参AAA是第一个yield的返回结果
result.next('BBB');
result.next();
4 async和await
async用于申明函数是异步,await用于等待一个异步方法执行完成。
4.1 async函数
ES2017 标准引入了 async 函数,使得异步操作变得更加方便
async函数是 Generator 函数的语法糖,与await配合使用;异步编程,同步处理
1)async函数返回一个 Promise 对象,return语句返回的值,会成为then方法回调函数的参数
2)async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到
async function test(){
let res1=await $.get('url');
console.log(res1);
let res2=await $.get('url');
console.log(res2)
}
test()
4.2 async和generator区别
async函数对比 generator 函数的优点
:
1)async函数内部自带执行器;
2)更好的语义
;async和await,比起星号和yield,语义更清楚
。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果
3)更广的适用性
;async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)
4)返回值是 Promise
;async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作
4.3 await
1)await必须写在 async 函数中
2)await命令后面是一个 Promise 对象,如果不是,会被转成一个 resolve 的 Promise 对象
3)await返回结果就是其后面Promise执行的结果,可能是resolved 或 rejected 的值
4.4 promise和await的区别
1、什么是Async/Await
async/await是写异步代码的新方式,使用的方式看起来像同步
async/await是基于Promise实现的,它不能用于普通的回调函数。
2、什么是promise
为了解决异步嵌套而产生,让代码更易于理解
区别:async/await让代码更像同步,进一步优化了代码
3. Promise和Async处理失败的时候的区别
(1)Promise错误可以在构造体里面被捕获,而async/await返回的是promise,可以通过catch直接捕获错误。
(2)await 后接的Promise.reject都必须被捕获,否则会中断执行