您的位置:首页 > 大数据 > 人工智能

Promise,Generator,async/await学习总结基本用法

2020-07-25 11:26 831 查看

promise

首先,

promise
是一种更优的异步编程解决方案,如果我们直接使用传统的回调方式去解决异步流程,就会避免不了大量的回调函数嵌套,形成
回调地狱
,

ajax.get(url,function(data1){
ajax.get(url,data1,function(data2){
ajax.get(url,data2,function(data3){
ajax.get(url,data3,function(data4){
//...形成回调地狱
})
})
})
})

为了解决回调地狱的问题,commonjs社区率先提出了promise规范,在ESMA2015中被标准化成为了语言规范。

promise就是一个对象,用来表示一个异步任务,结束以后是成功还是失败。
promise一共有三个状态,

pending(待定状态)
fulfilled(成功状态)
rejected(失败状态)

状态只能有pending到fulfilled,或者pending到rejected,且状态是不可逆的。
promise中有一个then方法,用来接收回调后的结果,then方法中有两个参数,第一个参数是

成功
的回调,第二个参数是
失败
的回调。

基本用法:

const promise = new Promise((resolve,reject)=>{
//这里用于兑现承诺

resolve("成功拉!!") // 兑现成功
//reject(new Error("失败拉!!")) // 兑现失败
})
promise.then((value)=>{
console.log(value) //输出的成功的值
},error=>{
//console.log(error) //输出的失败的值
})

promise配合ajax使用案列:

//封装ajax
function ajax(url){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest()
xhr.open('GET',url)
xhr.responseType ='json'
xhr.onload=function(){
if(this.status===200){
//代表成功
resolve(this.response)
}else{
reject(new Error(this.statusText))
}
}
xhr.send()
})
}

//使用
ajax('/api/test.json')
.then(data=>{
console.log(data) //请求成功的结果
},reason=>{
console.log(reason) //请求失败的原因
})

promise的链式调用

用来解决回调地狱的问题,是我们的代码更加的扁平化。

上面的代码可以这样使用:

//使用
ajax('/api/test.json')
.then(data=>{
console.log(data)//请求成功的结果
//promise 对象的then方法会返回一个全新的peomise对象
return ajax('/api/test2.json')  //返回第二个url请求的结果
},reason=>{
console.log(reason) //第一个url错误的捕获
})
//后面的then方法就是为上一个then返回的promise注册回调
.then((test2)=>{ //前面的then方法的返回值会作为后面then方法的回调的参数
console.log(test2) //输出的为第二个url返回的结果
return ajax('/api/test3.json')  //返回第三个url请求的结果
})
.then((test2)=>{
console.log(test2) //输出的为第三个url返回的结果
})

//....

Promise的异常处理

  1. 我们可以一层一层的捕获:
ajax('/api/test.json')
.then(data=>{
console.log(data)
return ajax('/api/test2.json')
},reason1=>{
console.log(reason1)//捕获url1的请求错误
})
.then((test2)=>{
console.log(test2)
return ajax('/api/test3.json')
},reason2=>{
console.log(reason2)//捕获url2的请求错误
})
.then((test2)=>{
console.log(test2)
},reason3=>{
console.log(reason3)//捕获url3的请求错误
})
  1. 可以使用promise提供的catch对我们的请求进行捕获
ajax('/api/test.json')
.then(data=>{
console.log(data)
return ajax('/api/test2.json')
})
.catch((reason)=>{
console.log(reason)
})

实际上 catch 方法就相当于我们的then方法的第一个值传入了undefined

ajax('/api/test.json')
.then(data=>{
console.log(data)
return ajax('/api/test2.json')
})
.then((undefined,reason)=>{
console.log(reason)
})

catch这种方式更适用于

链式调用
,它可以捕获到每次then回调的错误结果,我们可以这样用:

ajax('/api/test.json')
.then(data=>{
console.log(data)
return ajax('/api/test1.json')
})
.then(data=>{
console.log(data)
return ajax('/api/test2.json')
})
.catch((reason)=>{
console.log(reason) //1和2有一个发生错误都会捕获到
})

Promise中的静态方法

1.resolve() 快速创建一个成功的对象

Promise.resolve('33')
.then((value)=>{
console.log(value)
})

这种写法等同于:

new Promise((resolve,reject)=>{
resolve("成功拉!!")
})
  1. reject() 快速创建一个失败的promise对象
Promise.reject(new Error('失败!!!'))
.then((value)=>{
console.log(value)
})

Promise.all()

promise并行执行的方法

Promise.all()
这个方法可以将
多个promise
合并为
一个promise
统一进行管理

Promise.all()
方法接收的是一个
数组
,数组中的每一个元素是一个
promise对象
,我们可以把这些promise对象看作是一个个的
promise任务
Promise.all()
方法会返回一个
全新的promise对象

所有的promise
都完成过后,我们返回的全新的promise才会完成,成功的返回的是一个
数组
,包含了每一个promise对象成功返回的结果

如果

有一个promise失败
了,这个promise.all()就会以
失败
结束

var promise = new Promise.all([
ajax('/api/test1.json'),
ajax('/api/test2.json'),
ajax('/api/test3.json')
])

promise.then(value=>{
//所有的promise都完成过后,才会打印value
//value为一个数组
})
.catch(err=>{
console.log(err) //有一个失败就会被捕获到错误信息
})

Promise.race()

Promise.race()也是把多个promise组合到一起的方法

与promise.all()的相同点:
都是传递一个数组

不同点:

promise.all()等待所有任务结束才会结束,Promise.race()只会等待第一个结束的任务,就是说Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态

let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
},1000)
})

let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('failed')
}, 500)
})

Promise.race([p1, p2]).then((result) => {
console.log(result) //
}).catch((error) => {
console.log(error)  // 打印的是 'failed'
})

Generator

generator(生成器)是ES6标准引入的新的数据类型,它是一种更优的异步编程解决方案。

基本用法:跟普通函数声明时的区别是加了一个*号

function *foo(){
console.log("generator")
}
foo()

上面的代码并不会执行,我们只有调用foo()函数的next()方法才会执行foo函数

function *foo(){
console.log("generator")
}
foo().next() // generator

通过yield语句可以在生成器函数内部暂停代码的执行使其挂起,此时生成器函数仍然是运行并且是活跃的,其内部资源都会保留下来,只不过是处在暂停状态。
在迭代器上调用next()方法可以使代码从暂停的位置开始继续往下执行。

function *foo(){
const res =  yield "keke"
console.log(res) //ff next方法传递过来的值
}
}
const generator = foo()
const result = generator.next() //result表示接收到的值
console.log(result)//{ value: 'keke', done: false }
generator.next("ff")

用generator进行异步操作处理:

function ajax(url){
return new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest()
xhr.open('GET',url)
xhr.responseType='json'

xhr.onload=function(){
if(this.status===200){
//代表成功
resolve(this.response)
}else{
reject(new Error(this.statusText))
}
}
xhr.send()
})
}

**使用 generator 处理异步:**
function *main(){
//使用try catch捕获异常
try{
const url = yield ajax('/api/test.json')
console.log(url) //拿到返回值
}catch(err){
console.log(err)
}
}
const generator = main()
const result = generator.next()
//result.value是一个promise对象,我们可以调用then方法获取data
result.value.then((data)=>{
generator.next(data)
},reason=>{
generator.throw(new Error(reason)) //捕获到错误扔出
})

处理多个异步

function* main() {
try {
const url = yield ajax('/api/test.json')
console.log(url) //拿到url返回值
const url2 = yield ajax('/api/test2.json')
console.log(url2) //拿到url2返回值
const url3 = yield ajax('/api/test3.json')
console.log(url3) //拿到url3返回值
} catch (err) {
console.log(err)
}
}
const generator = main()
const result = generator.next()
result.value.then((data) => {
const result2 = generator.next(data)
if (result2.done) return
result2.value.then((data) => {
const result3 = generator.next(data)
if (result3.done) return
result3.value.then((data) => {
generator.next(data)
})
})
}, reason => {
generator.throw(new Error(reason))
})

上面的代码我们可以写到一个递归函数里面,结束条件是当 reault.done为true的时候结束,对代码进行优化:

const generator = main()
const result = generator.next()

//封装到getGenerators函数里面,
function getGenerators(result){
if(!result.done){
result.value.then(data=>{
getGenerators(generator.next(data))
},err=>{
generator.throw(new Error(reason))
})
}
}

//调用
getGenerators(result)

async/await

是es2017新增的一个异步处理方案,它是一个语法糖,用起来很简单

用法如下:

//在函数前面加async
async function main() {
try {
//await代表等待
const url = await ajax('/api/test.json')
console.log(url) //拿到url返回值

const url2 = await ajax('/api/test2.json')
console.log(url2) //拿到url2返回值

const url3 = await ajax('/api/test3.json')
console.log(url3) //拿到url3返回值
} catch (err) {
console.log(err)
}
}

main()
``
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: