目录
为了解决回调地狱的问题 es6给我们提供了一种方案——promise
es6给我们提供了一个构造函数——Promise
用法:
- //promise使用方式
- //1.使用Promise构造函数 实例化对象
- let p = new Promise((res,rej)=>{
- //res:成功态函数
- //rej:失败态函数
- //promise的实例对象 存在三种状态 默认状态为 等待态 如果调用res函数就会转变为成功态 调用rej函数 转变为失败态
- //注意:promise实例对象 只能转变一次状态
- res(成功态结果数据);//转变为成功态
- rej(失败态结果数据);//转变为失败态
- })
- //2.promise对象 可以调用两个方法——then catch
- //then方法 是成功态promise对象调用的方法
- p.then((data)=>{
- //形参data将会接收到 成功态的结果
- })
- //catch方法 是失败态promise对象调用的方法
- p.catch((err)=>{
- //形参err将会接收到 失败态的结果
- })
一般我们在使用promise的时候 都会 在Promise构造函数中 写入异步代码(定时器、事件等) 这样就可以避免回调函数的嵌套
例如:
- //需求:延迟两秒 打印 成功了
- let p = new Promise((res,rej)=>{
- setTimeout(()=>{
- res("成功了");
- },2000)
- })
- //2.promise实例对象调用then(成功态) 和 catch(失败态)方法
- p.then((data)=>{
- console.log(data);
- })
-
- //promise执行顺序
- /*
- 1.调用Promise构造函数 创建promise对象
- 2.等待Promise构造函数中的回调函数里的异步代码执行
- 3.异步代码执行之后 就会对应的改变promise对象的状态
- 4.状态改变完之后 才会对应调用then 或 catch方法
- */
promise的then和catch方法 可以链式调用
then和catch的链式调用
- let salary = 10001
- let p = new Promise((res,rej)=>{
- if(salary>10000){
- res("成功了");
- }else{
- rej("失败了")
- }
- })
- p.then((data)=>{
- console.log(data);
- }).catch((err)=>{
- console.log(err);
- })
then和then也可以链式调用
- let salary = 10001
- let p = new Promise((res,rej)=>{
- if(salary>10000){
- res("成功了");
- }else{
- rej("失败了")
- }
- })
- p.then((data)=>{
- console.log(data);
- return 数据
- }).then((data)=>{
- //data中接收到的是 上一个then方法 的 回调函数中的返回值
- console.log(data);
- })...
总结:
then和catch方法 之所以可以链式调用 是因为 这两个方法 的 返回值 是 promise对象
注意:then方法的链式调用 除了第一个then方法 中回调函数可以接收到成功态数据之外 其他then方法中回调函数 接收到的数据 都是上一个then方法回调函数的返回值
promise解决回调地狱问题
- //解决回调地狱
- //promise解决问题
- let fn = () => {
- //在函数中 我们生成promise对象 并将promise对象返回出去
- let p = new Promise((res, rej) => {
- setTimeout(() => {
- res("aaa")
- }, 2000)
- })
- return p;
- }
- //下面我们使用promise的写法 来实现上述效果
- let fn1 = (data)=>{
- console.log(data);
- return fn();//返回的是fn() promise对象 如果上一个then方法的回调函数中 返回的是promise对象 下一个then方法的回调函数中 接收到的就是 前面返回的promise对象的成功态数据
- }
- fn().then(fn1).then(fn1).then(fn1).then(fn1).then(fn1).then(fn1)
promise的合并
在promise的使用过程中 我们可以将多个promise对象 合并为一个 使用的方法是Promise.all 用法:let 变量 = Promise.all([promise对象1,对象2,对象3,...]) 合并出来的promise对象 也可以正常调用 then 和 catach 方法 如果所有合并的promise对象状态都是成功态 则 调用then方法 接收到的结果是一个数组 数组中包含所有promise对象的成功态数据 如果所有合并的promise对象有一个状态为失败态 则 调用catch方法 接收到失败态数据 如果有多个promise为失败态 则 调用catch方法 接收第一个出现失败态的promise对象的失败态数据 后面的失败态promise对象就不管了
promise并没有从根本上解决 回调函数的写法
为了进一步的优化 在es8中 提出了 async和await修饰符 来解决回调地狱问题
基础用法:
async:是一个函数修饰符 专门用来修饰函数 使用async修饰过的函数 函数体中 才能使用await
- //普通函数
- async function 函数名(){}
- //声明变量的函数
- let 变量名 = async ()=>{}
- //方法函数
- {
- async fn(){
-
- }
- }
- //事件处理函数
- 元素.onclick = async function(){}
- //箭头函数
- async ()=>{}
-
- //匿名函数
- (async function(){})
await:是一个关键字 这个关键字 只能用在 被async修饰过的函数体内部
await也是一个修饰符 理论上讲 可以修饰任何数据 但我们一般用await 修饰promise对象
- async function 函数名(){
- let 变量 = await promise对象;
- }
当我们使用await修饰promise对象的时候 await会自动接收到 promise对象的成功态数据(不需要单独调用then)
注意:在async修饰的函数中 我们每遇到一个await 就会等待其后的promise对象的状态发生变化 状态变为成功态之后 接收数据 继续向下执行
- async function 函数名(){
- let 变量1 = await promise对象;//遇到await 就等待其后的promise对象改状态
- console.log(变量1)//执行
- let 变量2 = await promise对象;//再次遇到await 再等待promise对象改状态
- console.log(变量2)//执行
- let 变量3 = await promise对象;//再次遇到await 再等待promise对象改状态
- console.log(变量3)//执行
- ...
- }
async-await解决回调地狱问题
- //1.封装一个用来创建promise对象的函数 异步代码写在promise构造函数的回调里面
- let fn = () => {
- let p = new Promise((res, rej) => {
- setTimeout(() => {
- res("aaa")
- }, 2000)
- })
- return p
- }
- //2.编写async修饰的函数 并在函数内部 通过await 接收promise对象的成功态数据
- let fn1 = async () => {
- for (let i = 0; i < 6; i++) {
- console.log(await fn());
- }
- }
- fn1()
使用await的函数 必须 用 async修饰
没遇到一次 await 就会 等待一次