大白话透彻讲解 Promise 的使用,读完你就懂了
一、为什么使用Promise?
我们知道 js 执行的时候,一次只能执行一个任务,它会阻塞其他任务。由于这个缺陷导致 js 的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以使用回调函数执行。
常见的异步模式有以下几种:
- 定时器
- 接口调用
- 事件函数
// setTimeout 示例
function callBack(){
console.log('执行完成')
}
console.log('before setTimeout')
setTimeout(callBack,1000)// 1秒后调用callBack函数
console.log('after setTimeout')
运行后控制台输出结果为:
before setTimeout
after setTimeout
执行完成 //1秒后打印上述定时器是在固定时间触发某个回调函数。
对于 ajax 网络请求就没有这么简单了,可能有多个网络请求是关联的,先执行某个请求返回结果后,第一个返回结果作为第二个请求的参数,调用第二个网络请求。如此,如果业务复杂,网络请求太多时,回调也很多,容易出现回调地狱。所以 Promise 出现了,专门解决异步回调地狱问题。
Promise 翻译成中文:承诺、保证。
通俗地讲,Promise 就像一个容器,里面存放着未来才会结束,返回结果的容器,返回的结果只需要在出口处接收就好了。从语法上讲,Promise 是一个对象,从它可以获取异步操作的消息。
二、Promise基本使用
下列用到的所有定时器模拟我们的 ajax 请求。
Promise 实例化的时候,传入的参数是一个函数,函数中接收两个参数:
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
 resolve('123')
 },1000)
}).then(res=>{
 console.log(res) //1秒后打印123
})
传入的 resolve 和 reject 本身都是函数。其作用分别为:
resolve - 把 Promise 的状态从进行中变为成功状态。
reject - 把 Promise 的状态从进行中变为拒绝状态。
Promise的三种状态:
pending :进行中,表示 Promise 还在执行阶段,没有执行完成。
fulfilled:成功状态,表示 Promise 成功执行完成。
rejected:拒绝状态,表示 Promise 执行被拒绝,也就是失败。
Promise 的状态,只可能是其中一种状态,从进行中变为成功或失败状态之后,状态就固定了,不会再发生改变。
Promise.then
执行 resolve 时,Promise 状态变为 fulfilled ,会执行 .then 方法。then 方法接收的参数也是一个函数,函数中携带一个参数,该参数是 resolve(res) 返回的数据。
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
 resolve('哎呦喂')
 },1000)
}).then(res=>{
 console.log(res) //1秒后打印哎呦喂
})
Promise.catch
执行 reject 时,Promise 状态从 pending 变为 rejected,会执行 catch 方法,catch 方法接收的也是一个函数,函数中携带一个参数,该参数为 reject(err) 返回的数据。
const p = new Promise((resolve,reject)=>{
 setTimeout(()=>{
  reject('error message')
  },1000)
 }).then(res=>{
  console.log(res)//不执行
 }).catch(err=>{
  console.log('err',err)//1秒后打印 error message
})
三、Promise 链式调用
制作一个模拟网络请求:
- 第一次返回 a,
- 修改返回的结果为 aa,作为第二次网络请求返回的结果。
- 修改结果为 aaa,作为第三次返回结果。
const pp = new Promise((resolve,reject)=>{
 setTimeout(()=>{
  resolve('a')
 },1000)
}).then(res=>{
 console.log('res1',res) //1秒后打印 a
 return new Promise((resolve,reject)=>{
  setTimeout(()=>{
   resolve(res+'a')
   },1000)
 })
}).then(res=>{
  console.log('res',res) //2秒后打印 aa
  return new Promise((resolve,reject)=>{
   setTimeout(()=>{
    resolve(res+'a')
    },1000)
  })
 }).then(res=>{
  console.log('res3',res) //3秒后打印 aaa
})
这种场景其实就是接口的多层嵌套使用,Promise 可以把多层嵌套按照线性的方式进行书写,非常优雅。我们把 Promise 的多层嵌套调用就叫做链式调用。
上述实例,有三层嵌套就 new 了 3 个Promise,代码写得比较多,我们看看在实现功能的前提下如何能够简化。
四、Promise 嵌套使用的简写
promise传入的函数参数reject是一个非必传的参数,如果不需要处理失败时的结果时,我们可以省略掉 reject 。代码如下:
//简化1
const ppp = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('a')
},1000)
}).then(res=>{
console.log('res1',res)
return new Promise(resolve=>resolve(res+'a'))
}).then(res=>{
console.log('res',res)
return new Promise(resolve=>resolve(res+'a'))
}).then(res=>{
console.log('res3',res)
})
Promise 嵌套使用时,内层的 Promise 可以省略不写,所以我们可以直接把 Promise 相关的去掉,直接返回,代码如下:
//简化2
const pppp = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('a')
},1000)
}).then(res=>{
return res+'a'
}).then(res=>{
return res+'a'
}).then(res=>{
console.log('res3',res)
})
有的同学就在想,怎么都是成功状态的举例和简写,我们的失败状态catch可以简写吗?
答案是肯定的,我们简化为2层嵌套,与上述功能一致。
const ppppp = new Promise((resolve,reject)=>{
 setTimeout(()=>{
  reject('a')
 },1000)
}).catch(err=>{
 return new Promise((resolve,reject)=>{
  setTimeout(()=>{
   reject(err+'a')
  },1000)
 })
}).catch(err=>{
 console.log('err',err)
})
//简写1const pppppp = new Promise((resolve,reject)=>{
 setTimeout(()=>{
  reject('a')
  },1000)
 }).catch(err=>{
  return new Promise((resolve,reject)=>reject(err+'a'))
 }).catch(err=>{
  console.log('err',err)
 })
//简写2const ppppppp = new Promise((resolve,reject)=>{
 setTimeout(()=>{
  reject('a')
  },1000)
 }).catch(err=>{
  throw err+'a'
 }).catch(err=>{
  console.log('err',err)
})
注意:失败简写省略掉Promise时,使用的 throw 抛出异常。
五、Promise方法
5.1、all 方法
Promise.all 方法,提供了并行执行异步操作的能力,并且在所有异步操作完成之后,统一返回所有结果。具体使用如:
Promise.all([
new Promise(resolve=>resolve('a')),
new Promise(resolve=>resolve('b')),
]).then(res=>{
console.log('all',res)//【'a' , 'b'】
})
all 接收到的是一个数组,数组长度取决于 Promise 的个数。
一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各类资源,所有的都加载完后,再进行页面的初始化。
5.2、race方法
race翻译成中文:赛跑。就是谁跑得最快,谁才能触碰到终点的胜利线。
Promise.race 用法与 all 一样,只是返回结果上不同,它返回的是执行最快的那个 Promise 的结果。
Promise.race([
new Promise(resolve=>
setTimeout(()=>{
resolve('a')
},100)
),
new Promise(resolve=>
setTimeout(()=>{
resolve('a')
},200)
),
]).then(res=>{
console.log('race',res) // 返回 a
})
大白话透彻讲解 Promise 的使用,读完你就懂了的更多相关文章
- 大白话讲解Promise(一)
		去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ... 
- 大白话讲解Promise
		去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本 ... 
- [转]大白话讲解Promise(一)
		http://www.cnblogs.com/lvdabao/p/es6-promise-1.html 去年6月份, ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正 ... 
- 透彻掌握Promise的使用,读这篇就够了
		透彻掌握Promise的使用,读这篇就够了 Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. ... 
- 大白话讲解Promise(二)理解Promise规范
		上一篇我们讲解了ES6中Promise的用法,但是知道了用法还远远不够,作为一名专业的前端工程师,还必须通晓原理.所以,为了补全我们关于Promise的知识树,有必要理解Promise/A+规范,理解 ... 
- 大白话讲解Promise(三)搞懂jquery中的Promise
		前两篇我们讲了ES6中的Promise以及Promise/A+规范,在Promise的知识体系中,jquery当然是必不可少的一环,所以本篇就来讲讲jquery中的Promise,也就是我们所知道的D ... 
- 【转】大白话讲解Promise(一)
		原文地址:https://www.cnblogs.com/lvdabao/p/es6-promise-1.html ES6 Promise 先拉出来遛遛 复杂的概念先不讲,我们先简单粗暴地把Promi ... 
- 透彻掌握Promise的使用
		Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我们不能 ... 
- es6 -- 透彻掌握Promise的使用,读这篇就够了
		Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,而且还要掌握透彻.这篇文章的开头,主要跟大家分析一下,为什么会有Promise出现. 在实际的使用当中,有非常多的应用场景我们不能 ... 
随机推荐
- Python对系统数据进行采集监控——psutil
			大家好,我是辰哥- 今天给大家介绍一个可以获取当前系统信息的库--psutil 利用psutil库可以获取系统的一些信息,如cpu,内存等使用率,从而可以查看当前系统的使用情况,实时采集这些信息可以达 ... 
- CTF--[BJDCTF2020]Cookie is so stable 1(SSTI)
			从hint.php可以找到提示,要求观察cookies 打开flag.php可以看到需要输入用户名,多次试验后发现输入的用户名会以cookies的方式储存 使用dirsearch扫描没有发现什么有用的 ... 
- 零基础学Java之Java学习笔记(一):Java概述
			什么是Java? Java是一门面向对象编程语言,可以编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序. Java特点有哪些? 1.Java语言吸收了C++语言的各种优点,具有功能强大 ... 
- mysql删除大表更快的办法
			实现:巧用LINK(硬链接),原理:linux文件系统中硬链接相当于文件的入口,记录着ionde的信息.一个文件存在多个硬连接时,删除一个硬链接不会真正的删除ionde(存储文件的数据) # 创建硬链 ... 
- Spring详解(九)------事务管理
			1.事务介绍 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 这里我们以取钱的例子来讲解:比如你去ATM ... 
- 用宏实现HEX到ASCII ,ASCII 到HEX
			#define HEX2ASCII(value, data) do{ \ value = (value > 0x09)?(value+0x7):value; \ ... 
- mfc HackerTools释放资源
			作用: 在VC环境中除了我们所常用的Dialog.Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自定义的资源类型能做些什么呢?呵呵,用处多多. ... 
- The Programmer's Oath程序员的誓言----鲍勃·马丁大叔(Bob Martin)
			In order to defend and preserve the honor of the profession of computer programmers, I Promise that, ... 
- k8s 探针 exec多个判断条件条件 多个检测条件
			背景 1,之前我们的yaml文件里面有就绪探针. 2,探针是检测一个文件是否生成,生成了说明服务正常. 3,现在要加一个检测,也是一个文件是否存在并且不为空. 4,只有两个条件同时满足了 服务才算正常 ... 
- MySQL5.7 高可用高性能配置调优
			[client]default-character-set = utf8mb4[mysqld]### 基本属性配置port = 3306datadir=/data/mysql# 禁用主机名解析skip ... 
