JS 异步解决方案的发展历程以及优缺点

  1. 回调函数(callback)
setTimeout(() => {
    // callback 函数体
}, 1000)

缺点:回调地狱,不能用 try catch 捕获错误,不能 return
回调地狱的根本问题在于:
缺乏顺序性: 回调地狱导致的调试困难,和大脑的思维方式不符
嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身,即(控制反转)
嵌套函数过多的多话,很难处理错误

ajax('XXX1', () => {
    // callback 函数体
    ajax('XXX2', () => {
        // callback 函数体
        ajax('XXX3', () => {
            // callback 函数体
        })
    })
})

优点:解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。)
2. Promise
Promise就是为了解决callback的问题而产生的。
Promise 实现了链式调用,也就是说每次 then 后返回的都是一个全新 Promise,如果我们在 then 中 return ,return 的结果会被 Promise.resolve() 包装
优点:解决了回调地狱的问题

function promise(a) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve(a)
        }, 1000)
    })
}
var arr = [];
new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 1000)
}).then(val => {
    arr.push(val);
    //要执行下一步promise,必须return出来,后面的then才能收到
   return promise(2)
}).then(val => {
    arr.push(val);
    return promise(3)
}).then(val => {
    arr.push(val);
    console.log(arr)//返回[1,2,3]
})
 /*
            promise.all
            (三个异步方法可同步执行, 但是必须等最慢的方法执行完成后才可执行then)
            如果三个方法不相互依赖(没有调用顺序, 也不需要调用异步方法的返回值)可以使用
        */
        function fun(a,time) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(a)
                }, time)
            })
        }
        Promise.all([fun(1,1000),fun(2,2000),fun(3,3000)]).then(res=>{
            console.log(res)//返回[1,2,3]
        })

缺点:无法取消 Promise ,错误需要通过回调函数来捕获, 如果连续调用ajax,则需在错误方法throw err
3. Generator
特点:可以控制函数的执行,它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。其实整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用 yield 语句注明。

function* fetch() {
    yield ajax('XXX1', () => {})
    yield ajax('XXX2', () => {})
    yield ajax('XXX3', () => {})
}
let it = fetch()
let result1 = it.next()//执行第一个yield,next也可以获取函数的返回值, next是马上执行, 如果是异步方法则返回值捕获不到
let result2 = it.next()//执行第二个yield
let result3 = it.next()//执行第三个yield
  1. Async/await
    async、await 是异步的终极解决方案
    优点是:代码清晰,不用像 Promise 写一大堆 then 链,处理了回调地狱的问题
    缺点:await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低。
  var arr = [];
        //awit async
        function fun(a) {
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(a)
                }, 1000)
            })
        }
        async function load(){
            //代码会等待前一步执行完后再执行下一步
            // 如果这三个方法没有依赖性的话,完全可以使用 Promise.all 的方式
            // 如果有依赖性的话,其实就是解决回调地狱的例子了
            arr.push(await fun(1));
            arr.push(await fun(2));
            arr.push(await fun(3));
            console.log(arr)
        }
        load()
const asynchronous = time => {
            return new Promise((resolve, reject) => {
                time == 5000 && reject('时间过长')
                setTimeout(() => {
                    resolve(`${time}ms的异步执行完成`)
                }, time);
            })
        }

        /*
        在async函数中, 只要遇到await关键字的函数(这个函数需返回promise对象),
        函数的运行就会被阻塞, 必须等待第一个await执行完成,才会执行下面的语法块,
        其中await的resolve结果会直接返回出来,但reject的结果会当做异常处理
        并且async函数中可直接用try catch来捕获await中的异步异常
        */
        const fun = async () => {
            try {
                let res1 = await asynchronous(2000);
                let res2 = await asynchronous(2000);
                let res3 = await asynchronous(5000);
                console.log(res1, res2, res3)
            } catch (error) {
                console.log(error)
            }
        }
        fun()
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值