一次讲清promise
此文章主要讲解核心思想和基本用法,想要了解更多细节全面的使用方式,请阅读官方API
这篇文章假定你具备最基本的异步编程知识,例如知道什么是回调,知道什么是链式调用,同时具备最基本的单词量,例如page、user、promise、then、resovle、reject、pay、fix、order等等,如果你对这些单词非常陌生,那么你需要先花点时间补充一下你的英语
什么是异步操作?
所谓异步操作,指的是可以跟当前程序同时执行的操作。举例:
$("#page").scrolltop(0 ,1000); //使用1秒钟时间将页面滚动至顶部
$("#nav-float").hide (1000); //使用1秒钟时间将悬浮导航栏隐藏
只要你稍微有点异步编程经验,就应该知道,这两个方法会同时完成。
它们的编写顺序并不会影响它们的执行顺序
//异步操作的特点就是,不会打断当前程序的执行
//getUsers请求发出后,会立刻向下继续执行第二个请求
ajax("/getUsers",function(data) {
//回掉函数会在请求成功后调用
})
//resumelist请求会立刻开始,无论getUsers是否结束
ajax("/resumelist", function(data) {
})
//至于哪一个ajax先返回结果并执行回调函数,从代码的编写顺序上是无法确定的。
我们可以给异步操作做一个简单的定义
当一个操作开始执行后,主程序无需等待它的完成,可以继续向下执行。此时该操作可以跟主程序同时(并发)执行。这种操作我们就称之为异步操作。 通常当操作完成时,会执行一个我们事先设定好的回调函数来做后续的处理。
我们常见的异步操作例如:
- 添加定时器 setTimeout/setInterval
- 执行某个动画 animate
- 发起网络请求 request
异步会带来什么问题?
比如我们现在有两个动画,需要按顺序来执行,也就是第一个结束,第二个才能开始
这个时候可能有点麻烦,传统的解决方法是通过回调:
animateA(function( ){
animateB( );
})
这种方案显然不太好,如果有很多异步操作需要顺序执行,就会产生所谓的“回调地狱”
ajaxA(function( ){
ajaxB(function( ){
ajaxC(function( ){
ajaxD(function( ){
......
});
});
});
})
这种代码不管是写起来还是读起来都比较烦人。
我们来看下经过Promise改造后的样子(伪代码)
new Promise(ajaxA)
.then(ajaxB)
.then(ajaxC)
.then(ajaxD);
Promise的使用及原理
要熟练Promise的的使用,你必须要先搞懂它解决问题的原理
贴一段实际的Promise代码,你来感受一下先:
newPromise(resolve=>{
ajax("/pay/post", data=>resolve() );
}).then(resolve=>{
ajax("/order/fix", data=>{
//处理数据
})
})
上面的代码使用了ES6的箭头函数,虽然大大简化了代码的写法,
但对于初级程序猿来讲极不友好
读这种代码简直跟读金刚经差不多。
我们把代码还原成ES5的样子
new Promise(function(resolve){
ajax("/pay/post",function(data){
resolve();
})
}).then(function(){
ajax("/order/fix",function(data){
})
})
接下来,我们就按照费曼技巧来一步步的学习Promise是如何解决问题的
问题1, 作为一个异步函数,尤其像ajax这种网络请求,连我自己都不能确定函数的执行时间,Promise是怎么知道第一个函数什么时候结束的? 然后再开始执行下一个?
Promise并没有那么神奇,它并不能知道我们的函数什么时候结束,
你注意到上面代码中的第3行了吗
在ajax请求结束执行回调的时候,
我们调用了一个resolve()函数,这句代码非常的关键.
这其实就是在通知Promise,当前这个函数结束啦,
你可以开始执行下一个。 这时Promise就会去执行then里面的函数了。
问题2, 所以按照你的意思,如果我不调用这个方法,Promise就不知道这个函数有没有结束,那么then里面的函数就不会执行,也就是说我的第二个请求就永远不会发送了呗?
Bingo!! 恭喜你已经学会了逻辑推理+抢答。
问题3, 可是这个resolve函数是从哪来的? 需要我自己定义吗? 从代码上看它好像是个参数,那又是谁传入函数中的?
你得先弄明白Promise的基本结构
new Promise(函数1).then(函数2);
我们把函数1和函数2都以参数形式传给了一个Promise对象,
所以接下来函数1和2都会由这个Promise对象控制,
简单的说,函数1和函数2都会由Promise对象来执行。
所以在函数1执行时,参数也当然是由Promise对象传递进去的。
new Promise(function(resolve){
//resolve是Promise对象在调用函数时传入的参数
}).then(函数2);
问题4, Promise对象为啥要在执行第1个任务的时候,把这个resolve函数 传进来,有什么目的?
你说呢?
废屁,知道还用问你?
真是猪脑子,刚才不是已经说了吗?
Promise对象没办法知道我们的异步函数啥时候结束。
那我来问你, 如果你去车站接人,
可是你又不知道对方何时下车,你会咋办?
把我电话号码给他,快到了打我电话呗
没错,Promise解决问题也采用了同样的思路。
它传进来的resolve函数, 就好像一个对讲机,
当我们的异步任务要结束时,通过对讲机 来通知Promise对象。
也就是调用resolve方法
new Promise(function(resolve){
ajax("/pay/post",function(data){
//当请求结束时,通过调用resolve方法,通知Promise对象,该任务已完成
resolve(); //收到通知后,Promise会立刻开始函数2的执行
})
}).then(函数2);
懂了,所以这个resolve函数,必须在异步任务的最后调用(例如ajax的回调方法),相当于告诉Promise对象,该任务结束,请开始下一个。
完全正确
问题5, 所以Promise也不过如此嘛,它没有带来什么功能上的革命性变化, 因为使用传统的回调嵌套的方式,同样可以完成效果。 说白了它就是编码方式上的改进??
基本是这样的,但Promise带来的编码方式以及异步编程思路上的进步是非常巨大的。
问题6, 那如果我有ajaxA、ajaxB、ajaxC三个异步任务,想按照先A后B再C的顺序执行,像这样写行吗?
new Promise(function(resolve){
ajax("/AAA", function(){
resolve(); //通知Promise该任务结束
})
}).then(function(resolve){
ajax("/BBB", function(){
resolve();//通知Promise该任务结束
})
}).then(function(){
ajax("/CCC", function(){ //.... })
})
上面的这种写法是不对的。
Promise的中文含义是“承诺”,
则意味着,每一个Pormise对象,代表一次承诺
而每一次承诺,只能保证一个任务的顺序,也就是说
new Promise(A).then(B); 这句话表示, 只能保证A和B的顺序
一旦A执行完,B开始后,这次承诺也就兑现了,Promise对象也就失效了
那如果还有C呢? 我们就必须在函数B中,
重新创建新的Promise对象,来完成下一个承诺,具体的写法就像这样:
new Promise(函数1(resolve){
ajaxA("xxxx", function(){
resolve();//通知Promise该任务结束
})
}).then(函数2(){
//在函数2开始运行后,第一次创建的Promise对象完成使命,已经不能再继续工作。
//此时,我们创建并返回了新的Promise对象
return new Promise(function(resolve){
ajaxB("xxxx", function(){
resolve();//通知新的Promise对象该任务结束
})
})
}).then(函数3(){ //尽管这里使用了链式调用,但负责执行函数3的,已经是新的Promise对象了
// 如果,我们还有ajaxD需要顺序调用
// 那就必须在这里重新new Promise()对象了
ajaxC("xxx", function(){ })
})
问题7, 懂了,那Promise还有什么其它强大的功能吗?
有啊,例如: 如果我有 A,B,C 三个异步任务,ABC同时开始执行
当A,B,C三个任务全部都结束时,执任务D,
传统方法实现起来就比较复杂,Promise就非常简单,就像这样:
Promise.all([new Promise(A), new Promise(B), new Promise(C)])
.then(function(){
D();
});
问题8, 那如果我希望A,B,C其中任意一个任务完成,
就马上开始任务D,该怎么做?
Promise.race([new Promise(A), new Promise(B), new Promise(C)])
.then(function(){
D();
});
作者:千锋HTML5学院
链接:https://www.jianshu.com/p/9d3b59922089
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
一次讲清promise的更多相关文章
- 三千字讲清TypeScript与React的实战技巧
很多时候虽然我们了解了TypeScript相关的基础知识,但是这不足以保证我们在实际项目中可以灵活运用,比如现在绝大部分前端开发者的项目都是依赖于框架的,因此我们需要来讲一下React与TypeScr ...
- 一句话讲清URI、URL、URN
关于URI,URL ,URN URN(Uniform Resource Name):统一资源名称 URL(Uniform Resource Locator):统一资源定位符 URI(Uniform R ...
- 一个故事讲清NIO
假设某银行只有10个职员.该银行的业务流程分为以下4个步骤: 1) 顾客填申请表(5分钟): 2) 职员审核(1分钟): 3) 职员叫保安去金库取钱(3分钟): 4) 职员打印票据,并将钱和票据返回给 ...
- 清北学堂2017NOIP冬令营入学测试 P4744 A’s problem(a)
清北学堂2017NOIP冬令营入学测试 P4744 A's problem(a) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试题,每三天结算 ...
- 清北学堂2017NOIP冬令营入学测试
P4744 A's problem(a) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试题,每三天结算一次成绩.参与享优惠 描述 这是一道有背 ...
- Promise小书(长文)
promise基础 Promise是异步编程的一种解决方案.ES6 Promise的规范来源于Promises/A+社区,它有很多版本的实现. Promise比传统的解决方案(回调函数和事件)更合理和 ...
- javascript基础修炼(7)——Promise,异步,可靠性
开发者的javascript造诣取决于对[动态]和[异步]这两个词的理解水平. 一. 别人是开发者,你也是 Promise技术是[javascript异步编程]这个话题中非常重要的,它一度让我感到熟悉 ...
- 清北冬令营入学测试[ABCDEF]
http://tyvj.cn/Contest/861 [1.2.2017] 像我这种蒟蒻只做了前6道还有道不会只拿了暴力分 A 描述 这是一道有背景的题目,小A也是一个有故事的人.但可惜的是这里纸张太 ...
- promise、resolve、reject、拦截响应
Promise是一个接口,它用来处理的对象具有这样的特点:在未来某一时刻(主要是异步调用)会从服务端返回或者被填充属性.其核心是,promise是一个带有then()函数的对象. 使用promise机 ...
- Javascript的事件模型和Promise实现
1. Javascript的运行时模型——事件循环 JS的运行时是个单线程的运行时,它不像其他编程语言,比如C++,Java,C#这些可以进行多线程操作的语言.当它执行一个函数时,它只会一条路走到黑, ...
随机推荐
- 【BOOK】数据存储--MongoDB
MongoDB存储 1.链接MongoDB 指定数据库 指定集合 import pymongo ## 连接数据库 client = pymongo.MongoClient( ...
- 【离线数仓环境搭建】安装linux及安装JDK
创建新的虚拟机 配置网络 安装vim sudo yum install -y vim 修改免密 sudo vim /etc/sudoers (执行安装命令的时候,不再需要输入密码) 查看防火墙状态 s ...
- Android Studio 生成Jar包以及是否混淆打包等ZengYuanFinn博客等你来查看
1,Android studio生成jar包的前提是要确保生成的代码是引用的module工程: 2,在需要生成jar包的build.gradle(上图倒数第三行)中添加如下代码: //生成jar包 t ...
- 微信小程序-关闭某个页面分享
方式一: wx.hideShareMenu(); 方式二:
- A Novel Sequential Method to Train Physics Informed Neural Networks for Allen Cahn and Cahn Hilliard Equations
一种新的顺序方法去求解关于时间的方程.个人感觉论文很差.(方法不新颖,写作很无聊,排版也有问题,内容也表述不清). 本文提出一种利用单个神经网络,在连续时间段上顺序求解偏微分方程的新型方案.关键思想是 ...
- Python 元组tuple、 列表list、 字典dict、集合set、迭代器、生成器
一.元组: tuple Python 的元组与列表类似,不同之处在于元组的元素不能修改. 元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组 tup2 = (111, 22, 33, ...
- 【小记】如果 golang 内存不够了怎么办
在看 redis 1.0 源码时,总会看到需要申请内存的地方,如果申请不到需要大的内存就会返回 NULL,然后在调用层抛出 oom. 比如 listDup 中在复制特殊 value 或者加入新节点时都 ...
- 可汗儿童版kids安卓版下载安装教程
可汗儿童版kids安卓版幼儿版下载安装教程 点击下面 http://vip.ho27.com/Khan.apk 备用下载链接 天翼网盘下载安装就行 https://cloud.189.cn/t/6RV ...
- 记一次对peer的理解
今天在使用react-native开发项目的时候,想要使用async-storage. 我用的rn版本是18.2.0,不带async-storage,所以我需要自己安装下载. 于是执行命令: npm ...
- Pycharm实现sqlite数据库可视化