目录

一、什么是promise

二、 Promise格式及PromiseState

(1)pending

(2)fulfilled 或 resolved

(3)rejected

三、PromiseResult

四、promise链式调用

五、回调地狱

错误写法

正确写法

实例中优化


一、什么是promise

我们通常都会去 new 一个Promise,什么东西可以new啊? 是不是构造函数可以new, 通过控制台dir一下Promise

通过上面的输出,你可以知道promise是一个构造函数,而上面常见的几个方法,resolve、reject、catch、resolve 你不需要立即知道它是干嘛的,接下来 听鹅说

Promise是Es6新增的构造器,用来提优化异步代码的写法,Promise中文意为承诺,承诺它一段时间后返回给你最终的结果。

首先了解三个状态,用setTimeout模拟实现一个ajax

        pending===》resolve(fulfilled)

     let p1 = new Promise((resolve)=>{setTimeout(() => {resolve(1)}, 2000);})console.log(p1);

 pending===》rejcet(rejected)

 let p1 = new Promise((resolve,reject)=>{setTimeout(() => {reject(1)}, 2000);})console.log(p1);

三个状态

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled): 意味着操作成功完成。
  • 已拒绝(rejected): 意味着操作失败。

举个栗子吧,小秃和小花去表白,小秃说 我喜欢你,你喜欢我吗? 这时候 小花肯定有两种回复 答应和拒绝

pedding:你可以理解为小秃正则等待小花的回复,但是目前没有回复的准确结果,例如上面代码的setTimeout 等待的2秒就是等待时间

fulfilled:  代表 我同意啦 我也暗恋你很久了!

rejected: 代表 你不配 渣男!

二、 Promise格式及PromiseState

相信 我对上面的balabala 已经提取你学习promise的兴趣了,接下来进入正题 学习一下promise格式定义

 // 箭头函数   let p1 = new Promise((resolve,reject)=>{})// 普通声明let p2 = new Promise(function (resolve,reject) {}) 

创建promise对象时,它的参数是一个函数 如果他会报错  Uncaught TypeError: Promise resolver undefined is not a function at new Promise (<anonymous>)

而这个函数中的两个形参(resolve,reject) 也是函数形式,但这两个只是形参的名字 实际上你写什么都可以,只不过我们通常约定 写着两个形参名

(1)pending

pending:待定,是一个等待最终结果的状态,也是一个初始状态,如果你在函数中不调用resolve,reject最终都是一个一直等待的状态,但是不调用,并没有什么意义,一般常用与调用resolve、reject给与相应的状态,总结:你只需要知道这是一个等待最终结果的状态,至于之后会发生状态,并不会知道

 let p1 = new Promise((resolve,reject)=>{})

(2)fulfilled 或 resolved

fulfilled代表已兑现、成功 ,意思是承诺兑现了 从pending====>fulfilled 的过程,在之前的浏览器版本可能会出现resolved的情况都是代表成功,当调用resolve函数时 就会进入成功(fulfilled )的状态

         let p1 = new Promise((resolve,reject)=>{resolve(1)})

PromiseState代表状态,PromiseResult 代表值 resolve、reject 调用时传入的数据

(3)rejected

rejected: 代表拒绝,失败,意思是承诺没有实现从pending=》rejected的过程  当调用 失败(reject)的状态

         let p1 = new Promise((resolve,reject)=>{reject(1)})

 小结 

最初创建对象的状态是pending     当调用了 resolve方法时 就会进入 fulfilled 状态         当调用reject方法 就会进入 rejected 状态

当状态一旦发送改变 就不会重新改变  例如已经从pending  到 fulfilled 了就不会重新改变到 rejected

         let p1 = new Promise((resolve,reject)=>{resolve()reject()})console.log(p1);

在上面的代码只会从 pending状态到fulfilled状态,并不会去执行最后的rejected 状态

三、PromiseResult

         let p1 = new Promise((resolve,reject)=>{resolve(1)})console.log(p1);

通过resolve和rejected传入参数时通过打印就会发现PromiseResult的值(值可以是任意数据类型),怎么拿到PromiseResult的值呢

new Promise((resolve,reject)=>{resolve('123')}).then(res=>console.log(res+'成功就会执行')).catch(err=>{console.log(err+'失败就会执行')}).finally(()=>{console.log('不管成功还是失败都会执行');})

在then和catch方法中它的参数是一个回调函数,在这个回调函数中的参数中就可以拿到resolve传过来的值,也就是promiseValue,

当调用resolve函数时传过去的参数就会到.then中的回调函数的参数中    状态pending===》fulfilled

当调用reject函数时传过去的参数就会到.catch 中的回调函数的参数中     状态pending===》rejected

当然 你也可以省略定义p1的写法 

        new Promise((resolve,reject)=>{resolve('123')}).then(res=>console.log(res+'成功就会执行')).catch(err=>{console.log(err+'失败就会执行')}).finally(()=>{console.log('不管成功还是失败都会执行');})

 .then中也可以写两个参数   第二个参数是可选的

当状态是pending===》fulfilled状态时会到.then中的第一个参数中的函数  pending===》rejected  回到.then中的第二个参数中的函数

       new Promise((resolve,reject)=>{reject(123)}).then((res)=>{ console.log(res+'成功') },(err)=>{ console.log(err+'失败') })

当你不去接收处理的 rejected状态时  会报出Uncaught (in promise)   中文意为未兑现(承诺)

          new Promise((resolve,reject)=>{reject(123)}).then((res)=>{ console.log(res+'成功') })

 四、promise链式调用

 在了解链式调用之前 先知道在这个.then函数中返回的是仍一个新的promise对象

        let p1 = new Promise((resolve,reject)=>{resolve('123')})let p2 =  p1.then(res=>{})console.log(p2);console.log(p1===p2); //false

p2中的PromiseResult 拿到的返回值是p1.then 函数中的返回值而p1.then函数中 没有返回值  那么返回值就是undefined

p2的PromiseResult    =    p1.then的返回值

为什么p2拿到的状态是fulfilled呢?不是rejected呢

1. 当.then中返回的不是promise对象时(包括undefined),p2的状态 一直都是fulfilled

2.只有当.then中的 返回的是promsie对象 并且调用的状态是reject()就会失败 rejected

例如下面这个例子就会返回 rejected

        let p2 =  p1.then(()=>{let p = new Promise((resolve,reject)=>{reject()})return p})console.log(p2);

当 .then函数中出现错误时 p2拿到的PromiseState的值是rejected,PromiseValue拿到的值是.then中出现的错误

        let p1 = new Promise((resolve, reject) => {resolve()});let p2 = p1.then(()=> {console.log(a); // 这里故意犯错});console.log(p2);

既然 p2 也是一个promise对象 我们就可以继续使用.then, 接下来 链式调用就开始了

    let p1 = new Promise((resolve, rejected) => {resolve(1)})let p2 = p1.then((res) => {console.log(res);  //1return 2})p2.then((res)=>{console.log(res);  //2})

 你当然页可以省略定义变量名  一直.then .then ~~的写

  new Promise((resolve, rejected) => {resolve(1)}).then((res) => {console.log(res);return 2}).then((res) => {console.log(res);})

五、回调地狱

模拟ajax 回调地狱 每次调用setTimeout 都是拿到上一次的值-1

        function fn1(a) {setTimeout(() => {console.log(a);a--;setTimeout(() => {console.log(a);a--setTimeout(() => {console.log(a);a--setTimeout(() => {console.log(a);a--setTimeout(() => {console.log(a);}, 1000);}, 1000);}, 1000);}, 1000);}, 1000);}fn1(5)

看到上面的代码 像不像地狱级别的嵌套 如果每次ajax 都要拿上一次的值去发ajax 造成了很不好的维护性,读代码也很困难,如果解决呢,这就用到了promise

错误写法

promise为什么能解决回调地狱  例如下面这个例子并没有去解决回调地狱  仍然造成了回调地狱

        function fn1(a) {new Promise((res, rej) => {res(a)}).then((params) => {return new Promise((res, rej) => {setTimeout(() => {console.log(params);res(--params)return new Promise((res, rej) => {setTimeout(() => {console.log(params);   res(--params)return new Promise((res, rej) => {setTimeout(() => {console.log(params);   res(--params)return new Promise((res, rej) => {setTimeout(() => {console.log(params);   res(--params)return new Promise((res, rej) => {setTimeout(() => {console.log(params);   res(--params)}, 1000)})}, 1000)})}, 1000)})}, 1000)})}, 1000)})})}let a = 5fn1(a)

注意 优化成promise并不是在一个 .then里面 继续做操作   包括你在.then里继续new一个promise  并且一直嵌套这.then.then 还是会产生回调地狱,

正确写法

优化成 promise 发现就不会出现嵌套关系,而且不管写多少个 也是条条有序

    function fn1(a) {new Promise((res,rej)=>{res(a)}).then((params)=>{return  new Promise((res,rej)=>{setTimeout(() => {  console.log(params);res(--params) }, 1000) }) }).then((params)=>{return  new Promise((res,rej)=>{setTimeout(() => {  console.log(params);res(--params) }, 1000) }) }).then((params)=>{return  new Promise((res,rej)=>{setTimeout(() => {  console.log(params);res(--params) }, 1000) }) }).then((params)=>{return  new Promise((res,rej)=>{setTimeout(() => {  console.log(params);res(--params) }, 1000) }) }).then((params)=>{return  new Promise((res,rej)=>{setTimeout(() => {  console.log(params);res(--params) }, 1000) }) })        }let a=5fn1(a)

实例中优化

在下面中的demo中 在一个.then中又嵌套了两次.then  这就造成了回调地狱 ,你不需要关系内容 只需要知道如何解决

  return new Promise((resolve, reject) => {if (ctx.rootState.user.profile.token) {// 没有修改登录后的sku接口const oldGoods = ctx.state.list.find(it => it.skuId === oldSkuId)console.log(newSku)// 删除 拿到之前的skuId删除deleteCart([oldSkuId]).then(() => {// 添加最新的sku进入购物车return insertCart({ skuId: newSku.value.skuId, count: oldGoods.count }).then(() => {// 请求最新的数据return findCartList().then((data) => {ctx.commit('setCartList', data.result)resolve()})})})

优化

return new Promise((resolve, reject) => {if (ctx.rootState.user.profile.token) {// 没有修改登录后的sku接口const oldGoods = ctx.state.list.find(it => it.skuId === oldSkuId)console.log(newSku)// 删除 拿到之前的skuId删除deleteCart([oldSkuId]).then(() => { // 添加最新的sku进入购物车insertCart({ skuId: newSku.value.skuId, count: oldGoods.count })console.log(1)}).then(() => { findCartList();  }).then((data) => {ctx.commit('setCartList', data.result)resolve()})

再次优化 省略箭头函数中的大括号

      return new Promise((resolve, reject) => {if (ctx.rootState.user.profile.token) {// 没有修改登录后的sku接口const oldGoods = ctx.state.list.find(it => it.skuId === oldSkuId)console.log(newSku)// 删除 拿到之前的skuId删除deleteCart([oldSkuId])// 添加最新的sku进入购物车.then(() => insertCart({ skuId: newSku.value.skuId, count: oldGoods.count })).then(() => { findCartList(); console.log(2) }).then((data) => {ctx.commit('setCartList', data.result)resolve()})}
})
  • promise 属于微任务 如果你对js执行顺序感兴趣  JavaScript宏任务(macrotask)和 微任务(microtask) 执行顺序_奥特曼 的博客-CSDN博客_javascript macro

ES6 Promise(承诺)看这一篇就够了相关推荐

  1. OpenStack入门科普,看这一篇就够啦

    OpenStack入门科普,看这一篇就够啦 科技百分百 2019-07-06 10:06:00 作者 | 小枣君 来源 | 鲜枣课堂 大家好,我是小枣君. 最近几年,OpenStack这个词开始频繁出 ...

  2. api网关选型_如何轻松打造百亿流量API网关?看这一篇就够了(下)

    如何轻松打造百亿流量API网关?看这一篇就够了(上) 上篇整体描述了网关的背景,涉及职能.分类.定位环节,本篇进入本文的重点,将会具体谈下百亿级流量API网关的演进过程. 准备好瓜子花生小板凳开始积累 ...

  3. python装饰器功能是冒泡排序怎么做_传说中Python最难理解的点|看这完篇就够了(装饰器)...

    https://mp.weixin.qq.com/s/B6pEZLrayqzJfMtLqiAfpQ 1.什么是装饰器 网上有人是这么评价装饰器的,我觉得写的很有趣,比喻的很形象 每个人都有的内裤主要是 ...

  4. serviceloader java_【java编程】ServiceLoader使用看这一篇就够了

    转载:https://www.jianshu.com/p/7601ba434ff4 想必大家多多少少听过spi,具体的解释我就不多说了.但是它具体是怎么实现的呢?它的原理是什么呢?下面我就围绕这两个问 ...

  5. docker 删除所有镜像_关于 Docker 镜像的操作,看完这篇就够啦 !(下)| 文末福利...

    紧接着上篇<关于 Docker 镜像的操作,看完这篇就够啦 !(上)>,奉上下篇 !!! 镜像作为 Docker 三大核心概念中最重要的一个关键词,它有很多操作,是您想学习容器技术不得不掌 ...

  6. mysql ip比较大小_MySQL优化/面试,看这一篇就够了

    原文链接:http://www.zhenganwen.top/articles/2018/12/25/1565048860202.html 作者:Anwen~ 链接:https://www.nowco ...

  7. 基础 | 零散的MySql基础记不住,看这一篇就够啦

    ❝ 这是小小本周的第二篇,本篇将会着重的讲解关于MySql基础的内容,MySql基础看这一篇就够啦. ❞ 送书反馈与继续送书 之情小微信公众号第一次送书,Java深度调试技术,书已经被中奖者麦洛签收, ...

  8. 【系统架构设计师】软考高级职称,一次通过,倾尽所有,看完这篇就够了,论软件架构设计的重要性、本篇论文“未通过考试”,供分析参考

    [系统架构设计师]软考高级职称,一次通过,倾尽所有,看完这篇就够了,学习方法和技巧这里全都有. 论软件架构设计的重要性.本篇论文未通过考试(不合格),供分析参考. 目录 摘要 正文 结尾 摘要 201 ...

  9. 深度好文:云网络丢包故障定位,看这一篇就够了~

    深度好文:云网络丢包故障定位,看这一篇就够了~ https://mp.weixin.qq.com/s/-Q1AkxUr9xzGKwUMV-FQhQ Alex 高效运维 今天 来源:本文经授权转自公众号 ...

  10. 代理后台中间件_Golang Gin 实战(十三)| 中间件详解看这一篇就够了

    6000字大章带你死磕Golang Gin中间件 在Gin的整个实现中,中间件可谓是Gin的精髓.一个个中间件组成一条中间件链,对HTTP Request请求进行拦截处理,实现了代码的解耦和分离,并且 ...

最新文章

  1. 2018年这些UI设计趋势正在流行,跟上必拿高薪!
  2. 撩课-Web大前端每天5道面试题-Day39
  3. 广度优先搜索生成树怎么画_图的深度优先遍历与广度优先遍历以及最小生成树...
  4. CI框架源码学习笔记7——Utf8.php
  5. 日志的处理 —— 使用 log4j
  6. C++算法学习(分支限界法)
  7. Python List Comprehension
  8. windows 安装python2.7
  9. 3D物理引擎JiglibFlash
  10. win10系统怎么改奇摩输入法_流氓输入法脱坑工具,我终于卸载了用了十年的搜狗输入法 | 乐软博客...
  11. Python 手写体识别
  12. 修复文件关联-EXE文件关联被修改后所有应用程序都打不开
  13. 论文解读:《Deep-4mcw2v: 基于序列的预测器用于识别大肠桿菌中的 N4- 甲基胞嘧啶(4mC)位点》
  14. 寺庙公众号开发:vue实现祈福牌位的前端部分
  15. Hive大总结!!!
  16. 如何用annie在B站下载视频?
  17. html5的vidoe标签,HTML5的Video标签的属性,方法和事件
  18. html中js隐藏div的高度,javascript获取隐藏元素(display:none)的高度和宽度的方法
  19. 孙陶然将公司管理分为三个阶段
  20. 在大理,有没有见到段誉?

热门文章

  1. 抖音火爆的早安推送在线版,新功能速递,支持推送时间自定义,添加生日日期计算
  2. 老兵威武,后来居上——老兵ETC在不断崛起
  3. 树莓派能不能兼容linux,树莓派威武-Ubuntu Linux将会兼容所有树莓派产品
  4. 测试工具篇:postman技巧
  5. 不能联网的服务器上安装R包
  6. html5 canvas 烟花,html5 canvas酷炫的烟花爆炸动画特效
  7. 国内MBA项目提前批面试剩余场次:浙大iMBA今天最后一批截止
  8. Android中常见的4种线程池的理解(转)
  9. 观影网站影评信息管理系统
  10. 传说她是上海大学校花