异步编程方案

1.概念

  • javascript是单线程执行方式,为了避免耗时的任务形成阻塞,需要使用异步编程方案来解决。

  • 回调函数,是js中异步编程方式的根基

2.Promise异步编程方案

使用回调函数来定义异步任务结束后的操作

const promise = new Promise(function(resolve, reject){
    resolve(100)
    
    reject(new Error('promise reject'))
})

promise.then(function(res){
    console.log('success', res)
}, function(err){
    console.log(err)
})

2.1 常见使用误区

回调地狱(多层回调嵌套使用)

function getData(dataUrl){
    return new Promise(function(resolve, reject){
        if(success){
            resolve(res)
        }else{
            reject(err)
        }
    })
}

// 顺序打印res1,res2,res3...
getData(url1).then(function(res1){
    console.log(res1)
    getData(url2).then(function(){
        console.log(res2)
        getData(url3).then(function(){
            ...
        })
    })
})

2.2 链式调用

Promise 的 then 方法返回一个新的Promise实例,因此可以继续调用 then 方法,为这个新的Promise对象指定回调函数

getData(url1)
    .then(function(res1){
        console.log(res1)
        return getData(url2)
    })
    .then(function(res2){
        // 如果上一个then中回调函数的返回值是一个Promise,下一个then将为这个Promise指定回调
        console.log(res2)
        return getData(url3)
    })
    .then(function(res3){
        console.log(res3)
        return 'str'
    })
    .then(function(res4){
        // 上一个then中的回调函数的返回值(一个字符串),会作为下一个then中回调函数的参数
        console.log(res4)  //'str'
    })
    .then(function(res5){
        // 如果上一个then中的回调函数没有返回值,默认返回undefined
        congsole.log(res5)  //undefined
    })

2.3 异常处理

  • 链式调用中更推荐在catch方法中定义失败回调。
  • catch方法本质与then相同,相当于第一个参数也就是成功回调传的是undefined
  • catch是为上一个then返回的新的promise添加回调。如果then中的回调 返回值是一个promise,并且这个promise执行中出现了异常,在当前这个then中定义失败回调是捕获不到的,而链条上的异常是一直向后传递的,所以catch一定能捕获到。

2.4 静态方法

  • Promise.resolve()
  • Promise.reject()
  • Promise.all()
    • all方法的参数是一个promise对象数组,
    • 返回值是一个全新的promise对象,
    • 这个promise对象的成功回调的参数是每个promise执行的结果数组,
    • 只有所有promise都成功,新的promise才会是成功状态,只要有一个失败了,新的promise就以失败结束。
let promise = Promise.all([
    getData(url1),
    getData(url2),
    getData(url3)
])

promise.then(function(res){
    congsole.log(res)
    //[data1, data2, data3]
}).catch(function(err){
    congsole.log(err)
})
  • Promise.race()
    race方法的参数也是一个promise数组,与all方法不同的是,它不是等待所有异步任务完成,而是以第一个结束的任务为准。

3.Generator异步编程方案

生成器函数Generator,定义时在普通函数基础上加一个 * 号

function * fn(){
    consolo.log('start')
    
    let x = yield 123
    console.log(x)  //undefined
    let y = yield 456
    console.log(y)  //2468
    return 789
}

const generator = fn()

generator.next() //{value:123, done:false}
generator.next() //{value:456, done:false}
generator.next(2468) //{value:789, done:true}
  • 生成器函数调用后不会立即执行,而是返回一个生成器对象,调用该对象的next方法,函数才会开始执行
  • 当执行中遇到yield命令,暂停执行,并将yield后边的表达式的值作为返回的对象的value
  • next方法可以带一个参数,作为上一个yield表达式的返回值,否则yield表达式本身返回undefined

3.1 Generator 结合 Promise 的异步方案

function * main(){
    const data1 = yield getData(url1)
    congsole.log(data1)
    
    const data2 = yield getData(url2)
    congsole.log(data2)
    
    const data3 = yield getData(url3)
    congsole.log(data3)
}

const g = main()
const result = g.next()  //返回promise1

if(result.done) return
result.value.then(data => {
    const result2 = g.next(data)  //返回promise2,给data1赋值
    if(result2.done) return
    result2.value.then(data => {
        conse result3 = g.next(data) //返回pronise3,给data2赋值
        if(result3.done) return
        result3.value.then(data => {
            g.next(data)  //返回undefined,done为true,给data3赋值
        })
    })
})

//使用递归方式执行Generator函数
function handleResult(result){
    if(result.done) return
    result.value.then(data => {
        handleResult(g.next(data))
    })
}
// const g = main()
// handleResult(g.next)

3.2 async / await 语法糖

  • async内置执行器,不需要调用next方法就能自动往下执行
  • async函数返回一个Promise对象,可以直接使用then方法指定回调
async function main(){
    const data1 = await getData(url1)
    congsole.log(data1)
    
    const data2 = await getData(url2)
    congsole.log(data2)
    
    const data3 = await getData(url3)
    congsole.log(data3)
}

const result = main()
result.then(() => {
    ...
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值