快速入门上手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,就是一个对象,用来传递异步操作的消息.它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个 ...
随机推荐
- Mac 系统如何利用软链接在根目录创建文件夹?
作者:泥瓦匠 出处:https://www.bysocket.com/2021-10-26/mac-create-files-from-the-root-directory.html Mac 操作系统 ...
- 2021.9.26考试总结[NOIP模拟62]
T1 set 从\(0\)到\(n\)前缀余数有\(n+1\)个,但只有\(n\)种取值,找到一样的两个输出区间即可. \(code:\) T1 #include<bits/stdc++.h&g ...
- 六个好习惯让你的PCB设计更优(转)
PCB layout工程师每天对着板子成千上万条走线,各种各样的封装,重复着拉线的工作,也许很多人会觉得是很枯燥无聊的工作内容.看似软件操作搬运工,其实设计人员在过程中要在各种设计规则之间做取舍,兼顾 ...
- 修炼Servlet
修炼Servlet 一.Servlet简单认识 1.Servlet是什么 Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的 ...
- Python:Ubuntu上出现错误 Could not load dynamic library 'libnvinfer.so.6' / 'libnvinfer_plugin.so.6'
运行一个py文件,出现如下的错误,原因是没有找到 libnvinfer.so.6 相关库的文件. 1 2021-01-04 18:41:17.324477: W tensorflow/stream_e ...
- MySQL实战优化之InnoDB整体架构
一.InnoDB 更新数据得整体架构 每个组件的作用说明: 用一条更新数据来说明每个主键得作用: update student set name = 'zhangsan' where id = 10 ...
- 像素反转 牛客网 程序员面试金典 C++ Python
像素反转 牛客网 程序员面试金典 题目描述 有一副由NxN矩阵表示的图像,这里每个像素用一个int表示,请编写一个算法,在不占用额外内存空间的情况下(即不使用缓存矩阵),将图像顺时针旋转90度. 给定 ...
- HTML基础-3
图像标签(<img>)和源属性(Src) 在 HTML 中,图像由 <img> 标签定义. <img> 是空标签,意思是说,它只包含属性,并且没有闭合标签. 要在页 ...
- 30分钟通过Kong实现.NET网关
什么是Kong Openrestry是一个基于Nginx与Lua的高性能平台,内部有大量的Lua库.其中ngx_lua_moudule使开发人员能使用Lua脚本调用Nginx模块.Kong是一个Ope ...
- IDM使用教程:利用IDM下载百度网盘文件
IDM是什么 其实我使用IDM下载器只是为了方便网页版百度网盘直接下载大于40M文件而已,大家知道文件过大必须打开客户端才能下载,这点对于我的破电脑感觉很烦躁,每次要等待它慢悠悠打开,然后动用我的超级 ...