快速入门上手JavaScript中的Promise
当我还是一个小白的时候,我翻了很多关于Promise介绍的文档,我一直没能理解所谓解决异步操作的痛点是什么意思
直到我翻了谷歌第一页的所有中文文档我才有所顿悟,其实从他的英文字面意思理解最为简单粗暴
这就是一个承诺,相当于在代码中提供一个在任何时候承诺之后要做什么事的方式,这个承诺可能会兑现也可能无法兑现,当然也可能在兑现的过程中
用这个来替代我们曾经需要写的回调函数,可以避免JavaScript程序中的回调地狱
所以先不去学习的语法,从另一个方式先理解,希望可以帮助你更好的学习或上手Promise
什么是Promise?
Promise是异步编程的一种解决方案,可以替代传统的解决方案,比如回调函数和事件
其在ES6中统一了用法,并提供了原生的Promise对象,Promise对象表示异步操作的最终完成(或失败)及其结果值
作为对象,Promise有以下两个特点:
- 对象的状态不受外界影响
- 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,
这也是Promise这个名字的由来,它的英语意思就是承诺,表示其他手段无法改变
- 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,
- 一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态
pending:初始状态,不是成功或失败状态;
fulfilled(resolved):操作成功完成状态;
rejected:操作失败状态Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected,
只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,
就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果,
这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的
Promise的创建和用途
- 构造函数接受一个名为
executor的函数,此执行函数接受两个f函数参数,resolve和reject。
new Promise( /* executor */ function(resolve, reject { ... }) );
- Promise通常用于阻塞代码和异步操作,其中包括文件调用,API调用,DB调用,IO调用等等
- 这些异步操作的启动发生在执行函数中,如果异步操作成功,则通过
promise的创建者调用resolve()函数返回预期结果,
同样,如果出现意外错误,则通过调用reject()函数传递错误具体信息 - 由于
promise会立即执行,我们无法检查promise的初始状态,所以创建一个需要时间执行的promise最简单的方式就是
使用setTimeOut()函数,通过浏览器控制台的输出可以直观看到之前所说的状态,以及他的变化过程
var promiseFir = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve({
message: '与大家分享知识很开心!',
code: 200
});
}, 2000)
})
console.log(promiseFir);
setTimeout(function() {
console.log(promiseFir);
}, 2000)
Promise的方法
- 3种原型方法
// 用一个小故事举例,你是一个上学的孩子,你问你的妈妈要一个电话。她说: 这个月底我要买一部手机
var momsPromise = new Promise(function(resolve, reject) {
momsSavings = 20000; // 因为妈妈没有足够储蓄所以无法买到礼物
// momsSavings = 200000; // 如果妈妈有足够的储蓄就可以买到礼物
priceOfPhone = 60000;
if (momsSavings > priceOfPhone) {
resolve({
brand: "iphone",
model: "6s"
});
} else {
reject("我们没有足够的储蓄,让我们多存点钱吧。");
}
});
momsPromise.then(function(value) {
console.log("哇,我得到这个电话作为礼物 ", JSON.stringify(value));
});
momsPromise.catch(function(reason) {
console.log("妈妈不能给我买电话,因为 ", reason);
});
momsPromise.finally(function() {
console.log(
"不管妈妈能不能给我买个电话,我仍然爱她"
);
});
Promise.prototype.then(onFulfilled, onRejected) 链式操作
Promise.prototype.then()方法返回的是一个新的Promise对象,因此可以采用链式写法Promise.prototype.then()方法带有以下三个参数:成功回调,失败回调,前进回调,一般情况下只需要实现第一个,后面是可选的
function ptFir() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法1执行');
resolve('方法1执行完毕');
}, 2000)
})
}
function ptSec() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法2执行');
resolve('方法2执行完毕');
}, 1000)
})
}
function ptThi() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法3执行');
resolve('方法3执行完毕');
}, 3000)
})
}
ptFir().then(function(data) {
console.log('第一个回调:' + data);
return ptSec();
}).then(function(data) {
console.log('第二个回调:' + data);
return ptThi();
}).then(function(data) {
console.log('第三个回调:' + data);
return '还没完?该结束了吧!';
}).then(function(data) {
console.log(data);
})
Promise.prototype.catch(onRejected) 捕捉错误
Promise.prototype.catch()方法是Promise.prototype.then(null, rejection)的别名,用于指定发生错误时的回调函数Promise对象的错误具有"冒泡"性质,会一直向后传递,直到被捕获为止,也就是说,错误总是会被下一个catch语句捕获
promise().then(function(data) {
// todo something
}).catch(function(err) {
// 处理上个回调函数的错误
})
Promise.prototype.finally(onFinally) 最终操作
不管promise对象最后的状态,在执行完.then或catch指定的回调函数以后,都会执行finally方法指定的回调函数
promise().then(function(data) {
// todo something
}).catch(function(err) {
// 处理上个回调函数的错误
}).finally(function(result) {
// 处理then/catch之后必须执行的操作
})
Promise.resolve() / Promise.reject()
- 这两个是帮助方法或快捷方式,它们可以帮助您轻松创建
resolve和reject方法 - 需要注意的是:如果
Promise.resolve()方法的参数,
不是具有.then()方法的对象(又称thenable对象),则返回一个新的Promise对象,且它的状态为fulfilled;
如果Promise.resolve方法的参数是一个Promise对象的实例,则会被原封不动地返回 Promise.reject()方法同上
var promise = Promise.resolve('Hello,这里是执行成功的内容!');
// var promise = Promise.reject('出错了,这里是被发现的错误!'); // 成功和失败只会有一种状态哦
promise.then(function(data) {
console.log(data)
});
promise.catch(function(err) {
console.log(err)
});
Promise.all()
- 当你处理多个
promise时,最好先创建一个promise数组,然后对这些promise集执行必要的操作 Promise.all(iterable) 方法返回一个Promise实例,此实例在iterable参数内所有的promise- 都完成(resolved)或参数中不包含
promise时回调完成(resolve) - 如果参数中
promise有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败promise的结果 - 注意!!!这里的异步操作是并行执行的,等到它们都执行完后才会进到
then()里面,
并且all()方法会把所有异步操作的结果放进一个数组中传给then() - 下面的示例需要说明的内容
- 只有3个方法的状态都变成
fulfilled,p的状态才会变成fulfilled,此时3个方法的返回值组成一个数组,传递给p的回调函数 - 只要3个方法之中有一个被
rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数
- 只有3个方法的状态都变成
function ptFir() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法1执行');
resolve('方法1执行完毕');
}, 2000)
})
}
function ptSec() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法2执行');
resolve('方法2执行完毕');
}, 1000)
})
}
function ptThi() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('方法3执行');
resolve('方法3执行完毕');
}, 3000)
})
}
Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) {
console.log(data);
console.log({}.toString.call(data));
})
Promise.race()
Promise.race(iterable)方法返回一个promise,一旦迭代器中的某个promise解决或拒绝,返回的promise就会解决或拒绝all()方法的效果实际上是「谁跑的慢,以谁为准执行回调」 ,
那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race()方法,这个词本来就是赛跑的意思- 这个
race()方法有什么用呢?使用场景还是很多的,比如我们可以用race()给某个异步请求设置超时时间,
并且在超时后执行相应的操作
// ptFir(), ptSec(), ptThi() 同上
Promise.all([ptFir(), ptSec(), ptThi()]).then(function(data) {
console.log(data);
console.log({}.toString.call(data));
})
使用Promise的一些经验法则
- 进行异步操作或使用阻塞代码时,请使用
Promise - 为了代码的可读性,
resolve()方法对待.then(),reject()方法对应.catch() - 确保同时写入
.catch()和.then()方法来实现所有的promise - 如果在这两种情况下都需要做一些事情,请使用
.finally() - 我们只有一次改变每个
promise (单一原则) - 我们可以在一个
promise中添加多个处理程序 Promise对象中所有方法的返回类型,无论是静态方法还是原型方法,都是Promise- 在
all()方法中,无论哪个promise首先未完成,promise的顺序都保持在值变量中
参考文档一 ———— 彻底理解Javascript 中的 Promise
参考文档二 ———— 通俗浅显的理解Promise中的then
参考文档三 ———— 理解 Javascript 中的 Promise
参考文档四 ———— JavaScript Promise 对象

我是 fx67ll.com,如果您发现本文有什么错误,欢迎在评论区讨论指正,感谢您的阅读!
如果您喜欢这篇文章,欢迎访问我的 本文github仓库地址,为我点一颗Star,Thanks~
转发请注明参考文章地址,非常感谢!!!
快速入门上手JavaScript中的Promise的更多相关文章
- webpack快速入门——处理HTML中的图片
在webpack中是不喜欢你使用标签<img>来引入图片的,但是我们作前端的人特别热衷于这种写法, 国人也为此开发了一个:html-withimg-loader.他可以很好的处理我们在ht ...
- javascript中的promise和deferred:实践(二)
javascript中的promise和deferred:实践(二) 介绍: 在第一节呢,我花了大量的时间来介绍promises和deferreds的理论.现在呢,我们来看看jquery中的promi ...
- JavaScript中的Promise【期约】[未完成]
JavaScript中的Promise[期约] 期约主要有两大用途 首先是抽象地表示一个异步操作.期约的状态代表期约是否完成. 比如,假设期约要向服务器发送一个 HTTP 请求.请求返回 200~29 ...
- Vue.js——60分钟快速入门 开发· webpack 中文文档
转载于:http://www.cnblogs.com/keepfool/p/5619070.html http://www.css88.com/doc/webpack2/guides/get-star ...
- 通过一道笔试题浅谈javascript中的promise对象
因为前几天做了一个promise对象捕获错误的面试题目,所以这几天又重温了一下promise对象.现在借这道题来分享下一些很基础的知识点. 下面是一个面试题目,三个promise对象捕获错误的例子,返 ...
- Javascript中的Promise
Promise定义 Promise是CommonJs的规范之一,包含resolve,reject,done,fail,then等方法,能够帮助我们控制代码的流程,避免函数的多层嵌套.异步在web开发中 ...
- R语言快速入门上手
导言: 较早之前就听说R是一门便捷的数据分析工具,但由于课程设计的原因,一直没有空出足够时间来进行学习.最近自从决定本科毕业出来找工作之后,渐渐开始接触大数据行业的技术,现在觉得是时候把R拿下 ...
- 掌握JavaScript中的Promise,实现异步编程
事件循环 基本介绍 JavaScript是一门单线程的编程语言,所以没有真正意义上的并行特性. 为了协调事件处理.页面交互.脚本调用.UI渲染.网络请求等行为对主线程造成的影响,事件循环(event ...
- 彻底理解Javascript 中的 Promise(-------------------------------***---------------------------------)
ES6原生提供了 Promise 对象. 到底是何方妖怪呢?打出来看看: 所谓 Promise,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个 ...
随机推荐
- css如何简单设置文字溢出盒子显示省略号
1.单行文本溢出显示省略号单行文本溢出显示省略号,必须满足三个条件:(1)先强制一行内显示文本white-space:nowrap;(默认 normal自动换行)(2)超出的部分隐藏overflow: ...
- Golang通脉之面向对象
面向对象的三大特征: 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式 继承:使得子类具有父类的属性和方法或者重新定义.追加属性和方法等 多态:不同对象中同种行为的不同实现方式 Go并不是一个纯 ...
- 【UE4 C++】 启动 / 关闭外部exe、开启虚拟键盘
启动/关闭外部exe 引擎自带 FPlatformProcess::CreateProc() FPlatformProcess::TerminateProc() windows api ShellEx ...
- [软工顶级理解组] Alpha阶段事后分析
目录 设想和目标 计划 资源 变更管理 设计/实现 测试/发布 团队的角色,管理,合作 总结 质量提高 会议截图 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰 ...
- FastAPI 学习之路(五十九)封装统一的json返回处理工具
这之前的接口,我们返回的格式都是每个接口异常返回的数据格式都会不一样,我们处理起来没有那么方便,我们可以封装一个统一的json处理. 那么我们看下如何来实现呢 from fastapi import ...
- C语言教你写个‘浪漫烟花‘---特别漂亮
效果展示 动态图 总体框架 /***************************************** * 项目名称:浪漫烟花 * 项目描述:贴图 * 项目环境:vs2019 * 生成日期: ...
- 零基础学习C语言入门必备知识
今天跟大家一起从零学C语言: 1. C语言简介 1.1 C语言发展史 C语言是一种广泛使用的面向过程的计算机程序设计语言,既适合于系统程序设计,又适合于应用程序设计.C语言的发展历程大致如图1-1所示 ...
- 深入理解xLua基于IL代码注入的热更新原理
目前大部分手游都会采用热更新来解决应用商店审核周期长,无法满足快节奏迭代的问题.另外热更新能够有效降低版本升级所需的资源大小,节省玩家的时间和流量,这也使其成为移动游戏的主流更新方式之一. 热更新可以 ...
- Go并发编程--Mutex/RWMutex
目录 一.前言 二. Mutex 2.1 案例 三. 实现原理 3.1 锁的实现模式 3.2 Go Mutex 实现原理 3.2.1 加锁 3.2.2 解锁 四. 源码分析 4.1 Mutex基本结构 ...
- PE头详细分析
目录 PE头详细分析 0x00 前言 0x01 PE文件介绍 0x02 PE头详细分析 DOS头解析 NT头解析 标准PE头解析 可选PE头解析 可选PE头结构 基址 代码段地址 数据段地址 OEP程 ...