JS 回调地狱

一、什么是回调地狱

  • 以一堆 }) 结尾的金字塔,可称它为——“回调地狱”
  • 在JS中我们经常会大量使用异步回调,例如使用ajax请求

二、如何解决回调地狱

(一)使用ES6中的Promise

  1. Promise有三种状态:pending/resolve/reject 。pending就是未决,resolve可以理解为成功,reject可以理解为拒绝
  2. Promise常用的三种方法:
  • then 表示异步成功执行后的数据状态变为resolve
  • catch 表示异步失败后执行的数据状态变为reject
  • all表示把多个没有关系的Promise封装成一个Promise对象,使用then返回一个数组数据

例:使用Promise

//Promise 构造函数有两个变量:resolve 用于返回异步执行成功的函数;reject 用于返回异步执行失败的函数。配合then与catch一起使用
function f1(){
    var promise=new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve("promise yes");
        },1000)
    });
    return promise;
}
//使用then获取上一步resolve返回的数据
function f2(){
    return f1().then(function(data){
        return data+"vue";
    });
}
f2().then(function(data){
    console.log(data);
});
console.log("hello world");

在这里插入图片描述
先输出 hello word 后输出promise yesvue,说明Promise是异步执行的

问题:若过多的使用then 也会照成新的执行流程问题

(二)使用ES6中的Generator(生成器)

在JavaScript中,任何一个函数只要开始执行,便无法停止下来直到执行完成;但是,Generator提供这种能力

例:使用Generator

//用Promise分装一个异步请求模拟ajax
function f1() {
    let promise = new Promise(function(resolve, reject){
        setTimeout(function () {
            resolve("hello word");
        })
    });
    return promise;
}
//构建一个生成器函数
function* f(){
    let x = yield f1();
    console.log("ni hao");
}
//获取生成器的值
var it = f();
it.next().value.then(function(data){
    console.log(data);
});
console.log(123);
it.next();
console.log(it.next());
  • 先用Promise分装一个异步请求模拟ajax。
  • 构建一个生成器函数:在函数方法名前面加一个 * ,函数体中有一个yield关键字,它类似return,也是返回值。区别在于当程序执行到yield后会返回yield后面的表达式,并且程序暂停在这里保存当前值状态,程序只是暂停并没有中止。
  • 获取生成器的值:使用next()方法可以获取到yield第一次暂停的值返回的是{ value: 值 done: true } value表示yield返回的值,done表示是否迭代完毕;也可使用next(10)给yield设置下次执行的值。
  • 通过结果看到生成器也是异步执行。

执行结果如下:
在这里插入图片描述
(三)async/await (异步等待)

  1. async 函数是 Generator 函数的语法糖;使用关键字 async 来表示,在函数内部使用 await 来表示异步

  2. 相较于 Generator,async 函数的改进在于下面四点:

  • 内置执行器:Generator 函数的执行必须依靠执行器,而 async 函数自带执行器,调用方式跟普通函数的调用一样

  • 更好的语义:async 和 await 相较于 * 和 yield 更加语义化

  • 更广的适用性:co 模块约定,yield 命令后面只能是 Thunk 函数或 Promise对象。而 async 函数的 await 命令后面则可以是 Promise 或 原始类型的值(Number,string,boolean,但这时等同于同步操作)

  • 返回值是 Promise:async 函数返回值是 Promise 对象,比 Generator 函数返回的 Iterator 对象方便,可以直接使用 then() 方法进行调用

例:使用async/await

//封装异步请求
function f(){
    return new Promise(function(resolve, reject) {
        setTimeout(function(){
            resolve("hello word");
        },1000)
    })
}
//使用异步函数
async function a(){
    var data = await f();
    return data;
}
//获取值
var a = a();
a.then(function(data){
    console.log(data);
})
  • 封装异步请求;
  • 使用异步函数:函数前加async表示该函数为一异步函数,await 表示等待一个异步值的到来;
  • 获取值:异步函数返回的是一个Promise对象,return返回的值通过使用then来进行获取。

执行结果如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值