Promise知一二
Promise
1.Promise的前置知识
进程(厂房)
- 程序的运行环境
线程(工人)
线程是实际进行运算的东西
同步
- 通常情况代码都是自上向下一行一行执行的
- 前边的代码不执行后边的代码也不会执行
- 同步的代码执行会出现阻塞的情况
- 一行代码执行慢会影响到整个程序的执行
解决同步的问题:
java python
- 通过多线程来解决,但是一般消耗资源比较多
node.js
通过异步方式来解决
我们可以这么理解:客人就好比我们请求的数据,服务员就好比客户端,厨师就好比服务器,我们现在客人点菜,服务员接收到菜的名称信息,给厨师说,厨师开始做,厨师在做的时候,客人一直等,不能干其他的事情,这就是同步,只能干一件事,我们现在利用异步的方式,可以让客人在课桌上等着菜来,也不影响服务员接收下一个客人的点菜,这样就可以很好的处理同步所带来的堵塞问题
异步
- 一段代码的执行不会影响到其他的程序
- 异步的问题:
异步的代码无法通过
return
来设置返回值特点:
不会阻塞其他代码的执行
需要通过回调函数来返回结果
function sum(a, b, cb) {
setTimeout(() => {
cb(a + b) //调用箭头函数,把结果作为回调函数的参数
}, 1000)
} sum(123, 456, (result)=>{
console.log(result)
})
基于回调函数的异步带来的问题
代码的可读性差
可调试性差(造成回调地狱)
sum(123, 456, (result)=>{
sum(result, 7, (result)=>{
sum(result, 8, result => {
sum(result, 9, result => {
sum(result, 10, result => {
console.log(result)
})
})
})
})
})
解决问题:
- 需要一个东西,可以代替回调函数来给我们返回结果
Promise
横空出世- Promise是一个可以用来存储数据的对象
- Promise存储数据的方式比较特殊,这种特殊的方式使得Promise可以用来存储异步调用的数据
- Promise是一个可以用来存储数据的对象
2.Promise介绍
异步调用必须要通过回调函数来返回数据,当我们进行一些复杂的调用时,会出现回调地狱
问题:
异步必须通过回调函数来返回结果,回调函数增加就不容易处理
- Promise
- Promise可以帮助我们解决异步中的回调函数的问题
- Promise就是一个用来存储数据的容器
- 它拥有着一套特殊的存储数据的方式
- 这个方式使得它里面可以存储异步调用的结果
创建Promise
创建Promise时,构造函数中需要一个函数作为参数
Promise构造函数的回调函数,它会在创建Promise时调用,调用时会有两个参数传递进去
const promise = new Promise((resolve, reject)=>{
// resolve 和 reject 是两个函数,通过这两个函数可以向Promise中存储数据
// resolve 在执行正常的时候存储数据, reject 是在执行错误的时候存储数据
resolve('我是正常执行的时候调用的')
reject('我是错误执行的时候调用的')
//通过函数来访问Promise中添加数据,好处就是可以用来添加异步调用的数据
setTimeout(()=>{
resolve('异步中调用数据')
},2000)
throw new Error('出错了,调用的是reject')
})
从Promise中读取数据
可以通过Promise的实例方法
then
来读取Promise中存储的数据then需要两个回调作为参数,回调函数来获取Promise中的数据
通过resolve存储的数据,会调用第一函数返回,可以在第一个函数中编写处理数据的代码
通过reject存储数据或者出现异常时,会调用第二个函数返回,可以在第二个函数中编写处理异常的代码
promise.then((result)=>{
console.log('1',result)
},(reson)=>{
console.log('2',reason)
})
Promise中维护了两个隐藏属性:
- PromiseResult
- 用来存储数据
- PromiseState
- 记录Promise的状态(三种状态)
pending
(进行中)fulfilled
(完成)通过resolve存储数据时rejected
(拒绝,出错了)出错了或通过reject存储数据时
- state只能修改一次,修改以后永远不会在变
- 记录Promise的状态(三种状态)
- 流程:
- 当Promise创建时,PromiseState初始值为pending
- 当通过resolve存储数据时 PromiseState 变为fulfilled(完成)
- PromiseResult变为存储的数据
- 当通过reject存储数据或出错时 Promise 变为rejected(拒绝)
- PromiseResult变为存储的数据 或 异常对象
- 当通过resolve存储数据时 PromiseState 变为fulfilled(完成)
- 当我们通过then读取数据时,相当于为Promise设置了回调函数
- 如果PromiseState变为fulfilled,则调用then的第一个回调函数来返回数据
- 如果PromiseState变为rejected。则调用then的第二个回调函数来返回数据
- 当Promise创建时,PromiseState初始值为pending
const promise2 = new Promise((resolve, reject) => {
resolve("哈哈")
}) // console.log(promise2)
promise2.then(result => {
console.log(result)
}, reason => {
console.log("出错了")
})
- PromiseResult
catch()
用法和then类似,但是只需要一个回调函数作为参数catch() 中的回调只会在Promise被拒绝时才会调用
catch() 相当于 then(null, reason=>{})
catch() 就是一个专门处理Promise异常的方法
promise2.catch(reason => {
console.log(222222)
})
finally()
无论是正常存储数据还是出现异常了,finally总会执行
但是finally的回调函数中不会接收到数据
finally()通常用来编写一些无论成功与否都要执行的代码
promise2.finally(()=>{
console.log("没有什么能够阻挡我执行的!")
})
3.Promise详解
3.1Promise用法
Promise就是一个用来存储数据对象
,但是由于Promise存取的方式的特殊,所以可以直接将异步调用的结果存储到Promise中
function sum(a, b) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(a + b)
}, 1000)
})
}
//回调地狱式写法:
sum(123, 456).then(result => {
sum(result, 7).then(result =>{
sum(result, 8).then(result => {
console.log(result)
})
})
})
//promise写法:
sum(123, 456)
.then(result => result + 7)
.then(result => result + 8)
.then(result => console.log(result))
下来我们就解释一下为什么是这种链式调用
的形式:
promise中的then方法会返回一个新的Promise
,而我们接收并且输出的是Promise的PromiseResult的值,就像这样:then (return new Promise())
,
Promise中会存储回调函数的返回值,当前的参数是上一个链式调用的返回值
promise
.then(result => {
console.log("回调函数", result)
return "会作为下个then的参数"
})
.then(result => {
console.log("第二个then", result) //第二个then,会作为下个then的参数
return "taotao真快乐"
})
.then(result => {
console.log(result) //taotao真快乐
})
promise中的
- then (return new Promise())
- catch
- 这三个方法都会返回一个新的Promise, Promise中会存储回调函数的返回值
- finally
- finally的返回值,不会存储到新的Promise中
- 对Promise进行链式调用时,后面的方法(then和catch)读取的上一步的执行结果
- 如果上一步执行结果不是当前想要的结果,则跳过当前的方法,执行下一个方法
- 一般都把catch写到最后,只写一个,最后统一处理异常
- 当Promise出现异常时,而整个调用链中没有catch,则异常会向外抛出
3.2Promise静态方法
Promise.resolve()
创建一个立即完成的PromisePromise.resolve('成功调用时的数据').then(
(result)=>{
console.log(1111)
})
//相当于
new Promise((resolve, reject)=>{
resolve('成功调用时的数据')
}).then(result=>{
console.log(1111)
})
Promise.reject()
创建一个立即拒绝的PromisePromise.reject('错误')
Promise.all([...])
同时返回多个Promise的执行结果其中有一个报错,就返回错误
function sum(a, b){
return new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(a + b)
},1000)
})
}
//传递一个可迭代对象(类数组)
Promise.all(
sum(111, 222),
Promise.reject("哈哈"),
sum(222, 333),
sum(333, 444)
).then((result)=>{
console.log(result) //[ 579, 11, 77 ]
}).catch ((reason)=>{
console.log(reason) //'哈哈'
})
Promise.allSettled([...])
同时返回多个Promise的执行结果(无论成功或失败){status: 'fulfilled', value: 579}
{status: 'rejected', reason: '哈哈'}
Promise.allSettled([
sum(123, 456),
sum(5, 6),
Promise.reject("哈哈"),
sum(33, 44)
]).then(r => {
console.log(r)
}) //返回的结果如下:
[
{ status: 'fulfilled', value: 579 },
{ status: 'fulfilled', value: 11 },
{ status: 'rejected', reason: '哈哈' },
{ status: 'fulfilled', value: 77 }
]
Promise.race([...])
返回执行最快的Promise(不考虑对错)Promise.race([
Promise.reject(1111),
sum(123, 456),
sum(5, 6),
sum(33, 44)
]).then(r => {
console.log(r)
}).catch(r=>{
console.log(r)
})
//执行结果如下
1111
Promise.reject(1111),不用等定时器执行结束,直接就调用
Promise.any([...])
返回执行最快的完成的PromisePromise.any([
Promise.reject(1111),
Promise.reject(2222),
Promise.reject(3333),
]).then(r => {
console.log(r)
}).catch(r => {
console.log("错误", r)
})
Promise知一二的更多相关文章
- 浅谈JavaScript、ES5、ES6
// http://es6.ruanyifeng.com/#docs/intro (ES6 文档) 什么是JavaScript JavaScript一种动态类型.弱类型.基于原型的客户端脚本语言,用来 ...
- 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索
第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...
- ChartDirector应用笔记(一)
ChartDirector介绍 ChartDirector是一款小巧精细的商业图表库.其适用的语言范围非常广泛,包括.Net, Java, Asp, VB, PHP, Python, Ruby, C+ ...
- trie树(前缀树)
问题描述: Trie树,即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优 ...
- Codeforces Round #258 (Div. 2)[ABCD]
Codeforces Round #258 (Div. 2)[ABCD] ACM 题目地址:Codeforces Round #258 (Div. 2) A - Game With Sticks 题意 ...
- H5、React Native、Native应用对比分析
每日更新关注:http://weibo.com/hanjunqiang 新浪微博!iOS开发者交流QQ群: 446310206 "存在即合理".凡是存在的,都是合乎规律的.任何新 ...
- 从Trie树(字典树)谈到后缀树
转:http://blog.csdn.net/v_july_v/article/details/6897097 引言 常关注本blog的读者朋友想必看过此篇文章:从B树.B+树.B*树谈到R 树,这次 ...
- H5、React Native、Native性能区别选择
“存在即合理”.凡是存在的,都是合乎规律的.任何新事物的产生总要的它的道理:任何新事物的发展总是有着取代旧事物的能力.React Native来的正是时候,一则是因为H5发展到一定程度的受限:二则是移 ...
- 海量数据处理之Tire树(字典树)
参考博文:http://blog.csdn.net/v_july_v/article/details/6897097 第一部分.Trie树 1.1.什么是Trie树 Trie树,即字典树,又称单词查找 ...
- Unity3D 记第二次面试
2014-03-10 忍不住投递了几份简历大概有20个,总共收到面试电话2个,十分之一.一个是11号下午4点面试另一个是12号下午3点面试(后来没去至于原因下面有)12号没去,为什么?因为招聘要求“精 ...
随机推荐
- 在k8s集群中安装rook-ceph 1.8版本步骤
官方文档地址:https://rook.io/docs/rook/v1.8/quickstart.html Kubernetes 最小版本号 Kubernetes 最小版本号:Kubernetes v ...
- Solutions:Elastic SIEM - 适用于家庭和企业的安全防护 ( 三)
- Kibana探索数据(Discover)
总结说明: 1.先在Management/Kibana/Index Patterns 界面下添加索引模式(前提是有索引数据) 2.在Discover界面选中响应的索引模式 3.开启Kibana 查询语 ...
- 在图片不被裁剪时opencv绕图片中任意点旋转任意角度
opencv绕图片中任意角度旋转任意角度 最近在做项目需要把把图片绕图片中任意点旋转任意角度,考虑到自己旋转需要编写插值算法,所以想到了用opencv,但是网上都是围绕图片中点旋转任意角度的,都是 ...
- aws-cli命令-S3相关的操作及管理
在工作中,我们可能经常会将本地数据上传S3进行备份,或者将S3数据下载到本地 本文主要讲解下,工作中可能经常会用到的与S3相关的操作 1.将本地目录的数据同步到指定的S3位置,及s3资源管理 # 同步 ...
- POJ2728 Desert King (最小生成树、0/1分数规划)
显然的0/1分数规划问题,用二分来解决,检验mid,就用prim算法求最小生成树,看总边权是否大等于0即可验证. 1 #include<bits/stdc++.h> 2 using nam ...
- 洛谷P4304 TJOI2013 攻击装置 (二分图匹配)
题目大意:一个矩阵,一些点被拿掉,在棋盘上马走日,马之间不能落在同一点,求最多放几匹马. 采用对矩阵黑白染色,画个图可以发现:马可以走到的位置和他所处的位置颜色不同,将马和他可以走到的位置连边,最多可 ...
- mac通过docker一键部署MySQL8
目录 mac通过docker一键部署MySQL8 一.前言 二.系统配置 三.安装步骤 Dockerhub查看镜像地址 1.一键安装 1.1.克隆脚本 1.2.安装程序 1.2.1.安装程序详情 1. ...
- Hbase之权限控制
Hbase之权限控制 -- 只读权限 grant '{userName}','R','{namespaceName:tableName}' -- 写入权限 grant '{userName}','W' ...
- .net core-利用PdfSharpCore和SkiaSharp.QrCode 添加PDF二维码页眉
前序 由于去年的一个项目需要在PDF 添加公司二维码 ,当时在网上找了很多操作PDF方案,第一种Aspose.PDF,很遗憾 Aspose.PDF 有添加版权的背景还是页脚我忘记了,不适合公司项目,最 ...