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

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()
``
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值