当前位置: 首页 > news >正文

Promise,我是这么理解的!

一、promise不是承诺

Promise在英语里有希望、承诺之意,在Javascript,它是异步解决方案。有人质疑已经有了更高级异步解决方案async/await,还有必要了解promise?是的,因为大部分项目异步方案使用promise,除此之外,promise也是实现async/await的基础。最重要的,promise仍是前端面试热点。

Promise:统一异步操作方法控制器

二、大话promise

如果你看到标题便阅读本文,想必已经了解promise基础知识!

1、resolve不是完成

阮老师课程有句话,“为了行文方便,本章后面的resolved统一只指fulfilled状态”,说明resolved并不一定是代表完成。

//终于排到队了....
function bookDinner(msg) {
    return new Promise((resolve, reject) => {
            resolve(msg)
        }).then(msg => console.log("完成订单:", msg))
        .catch(msg => console.log("订单异常:", msg))
}复制代码

上例为举例排队订餐场景,排队过程中状态是pending。排到你后,收银台收银并给你一个号牌,需要等待取餐,这个时候状态便是resolved,收银台仅仅给了你一个订餐成功的承诺,人家比一定保证你能吃上。一旦发生异常或者其他事件,仍可能导致订单失败。

bookDinner(Promise.reject("厨师带着老板娘跑了!"))//'订单异常: 厨师带着老板娘跑了!'复制代码

resolved不能代表fullfilled

2、希望用不到的catch

上例中我们使用Promise构造函数创建promise实例,并赋予了实例不能改变的状态。在执行任务中我们使用到了catch方法,用于指定状态为rejected或发生错误的回调函数。

catch方法是then(null,rejection)或者then(undefined,rejection)的别名,那为什么会有catch方法?

  • 感官上更接近try/catch方法,代码易读;
  • 捕捉错误的能力,catch可以捕捉到前面promise对象(then方法也是promise对象)的错误;
let p = new Promise((resolve, reject) => {
    resolve()
})
//第一种:
p.then(() => { throw new Error('rejected') })
    .catch(v => console.log(v)) // "Error: rejected"
//第二种:
p.then(() => { throw new Error('rejected') }, v => console.log(v)) //报错复制代码
  • catch方法只能捕获其前的错误;
let p = new Promise((resolve, reject) => {
    resolve()
})
p.catch(err => console.log(err))
    .then(() => { throw new Error('catch后的报错') })//报错获取不到复制代码
  • catch方法报错可以在下一个catch方法获取,因为catchthen的变形。
let p = new Promise((resolve, reject) => {
    reject()
})
p.catch(() => { throw new Error('catch后的报错') })
    .catch(err => console.log(err)) //'Error: catch后的报错'复制代码

Promise 对象抛出的错误不会传递到外层代码,即不会影响其他任务正常执行,通俗的说法就是“Promise 会吃掉错误”。

console.log('start....')
let p = new Promise((resolve, reject) => {
    console.log('promise')
    throw new Error("是否会影响其他代码?")
})
p.then(v => console.log(v))
console.log('end!')
// start....
// promise
// end!
//报错:Uncaught (in promise) Error: 是否会影响其他代码?复制代码

3、高要求Promise.all

promise.all([]):数组内所有promise实例状态均为fullfilled,数组promise容器才为fullfilled。数组只要有一个状态rejected,数组promise容器状态九尾rejected。

这个方法确实挺有意思,还是以咱们点餐为例,食物和勺子都得具备才完成吃饭的任务,吃饭状态才能是fullfilled。任何一项不满足的话,对于吃饭任务来说,状态便是rejected

//获得食物
function getFood() {
    return Promise.resolve("盖饭")
}
//获得勺子
function getSpoon() {
    return Promise.resolve('勺子')
}
//吃饭
function eatFood() {
    return Promise.all([getFood(), getSpoon()])
}

eatFood().then(v => console.log('吃饭:',v))//'吃饭:["盖饭", "勺子"]'
    .catch(err => console.log(err)) 复制代码

如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()catch方法。

上边的例子我们稍加改变,服务员迟迟不给你拿勺子,这个时候,针对getSpoon这个任务报了个错,服务员立马知道了,拿来勺子,让你完成吃饭任务。其实是catch方法返回了一个新的实例。

//获得食物
function getFood() {
    return Promise.resolve("盖饭")
}
//获得勺子
function getSpoon() {
    return Promise.reject('还没给勺子')
}
let getSpoonAgin = getSpoon().then(v => v).catch(err => console.log(err))
//吃饭
function eatFood() {
    return Promise.all([getFood(), getSpoonAgin])
}

eatFood().then(v => console.log("吃饭:", v)) //'吃饭:["盖饭", undefined]'
    .catch(err => console.log("未能吃饭:", err))
}复制代码

4、竞争上岗Promise.race

promise.race:与promise.all类似,参数也是promise实例数组。哪个promise实例优先"到达",promise.race容器的状态就是先到达的promise实例状态。

继续点餐的例子,大家工作比较忙,中午只能等待15分钟,为了吃上饭你点了两份饭,毕竟胃容量有限,只能哪份先来就吃哪份(杠精们,不要抬杠哈!)当然此处只是举了两个任务状态都是fullfilled的例子。

function getFood1() {
    return Promise.resolve("盖饭")
}

function getFood2() {
    return Promise.resolve('饺子')
}

function eatFood() {
    return Promise.race([getFood1(), getFood2()])
}

eatFood().then(v => console.log("吃饭:", v)) //'吃饭: 盖饭'
    .catch(err => console.log("未能吃饭:", err))复制代码

三、写在最后

以上只是针对Promise运行方式以及部分方法进行说明,在项目实战中Promise的使用远比上边所说的例子复杂,希望本篇对于您理解promise异步解决方案有所帮助。

具体在使用中细节可以学习阮一峰老师ES6课程。

如果想要了解任务执行顺序的,可阅读聊聊前端面试之输出顺序

谢谢您的阅读,请多指教!


转载于:https://juejin.im/post/5c25bb756fb9a049dc025014

相关文章:

  • python 怎样使用单个反斜杠\
  • 在IPv6之前
  • 数据挖掘领域经典算法——CART算法
  • JavaScript原型的实际应用
  • 微软宣布Azure Function支持Python
  • adb
  • java监控工具VisualVM
  • linux学习day3
  • 10.linux命令之cal命令
  • 孔乙己的疑问:单例模式有几种写法
  • VBScript:WshShell对象
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • 任正非公开信深度解读:两年怎样改变了华为?
  • 华为:两年前要炸掉研发金字塔,今天要投入20亿美元提升软件质量
  • linux之常用命令的使用
  • 【每日笔记】【Go学习笔记】2019-01-10 codis proxy处理流程
  • ComponentOne 2017 V2版本正式发布
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • JavaScript异步流程控制的前世今生
  • js数组之filter
  • k8s如何管理Pod
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • Service Worker
  • 纯 javascript 半自动式下滑一定高度,导航栏固定
  • 基于 Babel 的 npm 包最小化设置
  • 技术发展面试
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 我感觉这是史上最牛的防sql注入方法类
  • 小李飞刀:SQL题目刷起来!
  •  一套莫尔斯电报听写、翻译系统
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 在Docker Swarm上部署Apache Storm:第1部分
  • 组复制官方翻译九、Group Replication Technical Details
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #if #elif #endif
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (cos^2 X)的定积分,求积分 ∫sin^2(x) dx
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)python旅游推荐系统 毕业设计 250623
  • (附源码)springboot美食分享系统 毕业设计 612231
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (转)微软牛津计划介绍——屌爆了的自然数据处理解决方案(人脸/语音识别,计算机视觉与语言理解)...
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET Micro Framework初体验
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET是什么
  • .net项目IIS、VS 附加进程调试
  • [Angular 基础] - 数据绑定(databinding)
  • [Asp.net MVC]Asp.net MVC5系列——Razor语法
  • [AutoSar]工程中的cpuload陷阱(三)测试
  • [BUUCTF]-PWN:wustctf2020_number_game解析(补码,整数漏洞)