Promise的使用

  1. 什么是Promies

简单地说Promise是异步编程的一种解决方案
Promise是ES6中的特性,Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不准确,按照标准来讲,resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。

什么是异步操作?

网络请求中,对端服务器处理需要时间,信息传递过程需要时间,不像我们本地调用一个js加法函数一样,直接获得1+1=2的结果。这里网络请求不是同步的有时延,不能立即得到结果。

如何处理异步事件?

对于网络请求这种,一般会使用回调函数,在服务端传给我数据成功后,调用回调函数。例如ajax调用。

$.ajax({success:function(){...}
})

如果碰到嵌套网络请求,例如第一次网络请求成功后回调函数再次发送网络请求,这种代码就会让人很难受。

$.ajax({success:function(){$.ajax({...})}
})

如果还需要再次网络请求,那么又要嵌套一层,这样的代码层次不分明很难读,也容易出问题。
2. Promise的基本使用

1、什么时候使用Promise
解决异步请求冗余这样的问题,promise就是用于封装异步请求的。
2、Promise对象

new Promise((resolve, reject) => {})

Promise对象的参数是一个函数(resolve, reject) => {},这个函数又有2个参数分别是resolve和reject。这2个参数本身也是函数,是不是有点绕?后面还有回调函数then( funcation(){} )的参数也是一个函数。

模拟定时器的异步事件

用定时器模拟网络请求,定时一秒为网络请求事件,用console.log()表示需要执行的代码。

//1.使用setTimeout模拟嵌套的三次网络请求
setTimeout(() => {//第一次请求console.log("hello world")//第一次处理代码setTimeout(() => {//第二次请求console.log("hello vuejs")//第二次处理代码setTimeout(() => {//第三次请求console.log("hello java")//第三次处理代码}, 1000)}, 1000)
}, 100

一层套一层,看起是不是很绕。

使用promise来处理异步操作

//参数 -> 函数
// resolve和reject本身也是函数
//then()的参数也是一个函数
new Promise((resolve, reject) => {setTimeout(() => {//第一次网络请求resolve()}, 1000)
}).then(() => {console.log("hello world")//第一次处理代码return new Promise((resolve, reject) => {setTimeout(() => {//第二次网络请求resolve()}, 1000).then(() => {console.log("hello vuejs")//第二次处理代码return new Promise((resolve, reject) => {setTimeout(() => {//第三次网络请求resolve()}, 1000)}).then(() => {console.log("hello java")//第三次处理代码})})})
})

是不是觉得代码还要更复杂了?仔细看看第一个如果使用了多个就找不到对应关系了。相反第二个流程就很清楚,调用resolve()就能跳转到then()方法就能执行处理代码,then()回调的返回值又是一个Promise对象。层次很明显,只要是then()必然就是执行处理代码,如果还有嵌套必然就是返回一个Promise对象,这样调用就像java中的StringBuffer的append()方法一样,链式调用。

new Promise((resolve, reject) => {setTimeout(() => {resolve('success')}, 1000).then(success => {console.log(success)})
})

setTimeout()模拟的是网络请求,而then()执行的是网络请求后的代码,这就将网络请求和请求得到响应后的操作分离了,每个地方干自己的事情。在resolve中传参了,那么在then()方法中的参数就有这个参数,例如data。

网络请求中也会有失败情况?例如网络堵塞。

如何处理失败情况,此时就要用到reject()

new Promise((resolve, reject) => {setTimeout(() => {reject('error message')}, 1000).catch(error => {console.log(error)})
})

此时reject(error),catch()方法捕获到reject()中的error。
合起来之后:

new Promise((resolve, reject) => {setTimeout(() => {// 成功的时候调用resolve()// resolve('hello world')// 失败的时候调用reject()reject('error message')}, 1000).then(success => {console.log(success)}).catch(error => {console.log(error)})
})

ajax例子:

new Promise((resolve, reject) => {$.ajax({success:function(){// 成功的时候调用resolve()// resolve('hello world')// 失败的时候调用reject()reject('error message')}}).then(success => {console.log(success)}).catch(error => {console.log(error)})
})

3、Promise的三种状态

pending:等待状态,比如正在进行的网络请求还未响应,或者定时器还没有到时间
fulfill:满足状态,当我们主动回调了resolve函数,就处于满足状态,并会回调then()
reject:拒绝状态,当我们主动回调reject函数,就处于该状态,并且会回调catch()
4、Promies的链式调用

网络请求响应结果为 hello ,打印hello
处理: hello world ,打印hello world
处理: hello world,vuejs ,打印hello world,vuejs
 new Promise((resolve, reject) => {setTimeout(() => {resolve('hello')}, 1000)}).then(res => {console.log(res)//打印helloreturn new Promise(resolve => {resolve(res + ' world')}).then(res => {console.log(res)//打印hello worldreturn new Promise(resolve => {resolve(res + ',vuejs')}).then(res => {console.log(res)//打印hello world,vuejs})})})

链式调用就是then()方法的返回值返回一个Promise对象继续调用then(),此外还有简写Promise.resolve()。

new Promise((resolve, reject) => {setTimeout(() => {resolve('hello')}, 1000)}).then(res => {console.log(res)//打印helloreturn Promise.resolve(res + ' world')}).then(res => {console.log(res)//打印hello worldreturn Promise.resolve(res + ',vuejs')}).then(res => {console.log(res)//打印hello world,vuejs})

还可以直接省略掉Promise.resolve()

    new Promise((resolve, reject) => {setTimeout(() => {resolve('hello')}, 1000)}).then(res => {console.log(res)//打印helloreturn res + ' world'}).then(res => {console.log(res)//打印hello worldreturn res + ',vuejs'}).then(res => {console.log(res)//打印hello world,vuejs})

如果中途发生异常,可以通过catch()捕获异常

    new Promise((resolve, reject) => {setTimeout(() => {resolve('hello')}, 1000)}).then(res => {console.log(res)//打印helloreturn res + ' world'}).then(res => {console.log(res)// return Promise.reject('error message')//发生异常throw 'error message' //抛出异常}).then(res => {console.log(res)//打印hello world,vuejs}).catch(error => {console.log(error)})
throw 'error message' //抛出异常

5、Promies的all和race使用

Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

var p = Promise.all([p1,p2,p3]);

上面代码中,Promise.all 方法接受一个数组作为参数,p1、p2、p3 都是 Promise 对象的实例。(Promise.all 方法的参数不一定是数组,但是必须具有 iterator 接口,且返回的每个成员都是 Promise 实例。)
p 的状态由 p1、p2、p3 决定,分成两种情况。

(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

下面是一个具体的例子。
// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function(id){return getJSON("/post/" + id + ".json");
});Promise.all(promises).then(function(posts) {// ...
}).catch(function(reason){// ...
});

Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

var p = Promise.race([p1,p2,p3]);

上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。

如果Promise.all方法和Promise.race方法的参数,不是Promise实例,就会先调用下面讲到的Promise.resolve方法,将参数转为Promise实例,再进一步处理。
6、Promise 优缺点

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

Promise的使用相关推荐

  1. setTimeout、setInterval、promise、async/await的顺序详解(多种情况,非常详细~)

    本文很长,列举的情况很多. 在阅读本文之前,如果您有充足的时间,请新建一个项目与本文一同实践. 每段代码都有对应的解释,但是自己动手尝试印象才会更深哦~ setInterval:表示多久执行一次,需要 ...

  2. C++多线程:异步操作std::async和std::promise

    文章目录 std::async 简介 使用案例 std::promise 简介 成员函数 总结 之前的文章中提到了C++多线程中的异步操作机制 C++ 多线程:future 异步访问类(线程之间安全便 ...

  3. ES6中的Promise详解

    Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷. 定义 Promise 是一个对象,它用来标识 JavaScri ...

  4. 关于ES6中Promise的应用-顺序合并Promise,并将返回结果以数组的形式输出

    1.Promise 基础知识梳理 创建一个Promise实例 const promise = new Promise(function(resolve, reject) {if (success){r ...

  5. promise实现多个请求并行串行执行

    早上查资料,偶然发现这个话题,发现自己并不会,于是乎,下来研究了一下. 想想之前我们用jquery写请求的时候,要实现请求的串行执行,我们可能是这么做的. $.ajax({url: '',data: ...

  6. 异步编程之Promise(2):探究原理

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  7. 自己动手写cpu pdf_自己动手写 Promise

    这段时间在学习Promise,但始终不得要领.为了更好地理解Promise,我决定自己实现一个简易版的Promise,以学习Promise工作原理.该工程名为ToyPromise,仓库地址如下: ht ...

  8. promise 和 async await区别

     什么是Async/Await? async/await是写异步代码的新方式,以前的方法有回调函数和Promise. async/await是基于Promise实现的,它不能用于普通的回调函数. as ...

  9. Promise - js异步控制神器

    微信小程序开发交流qq群   581478349    承接微信小程序开发.扫码加微信. 正文: 首先给来一个简单的demo看看Promise是怎么使用的: <!DOCTYPE html> ...

  10. Promise的实例用法

    设定函数 function chiFan() {return new Promise(function(resolve, reject) {console.log("chiFan" ...

最新文章

  1. 调试异常 Free Heap block xxxxxxxx modified at xxxxxxxx after it was freed
  2. 解决 No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi 的问题
  3. Reindex SQL Server DB table
  4. C++(21)--Astah uml 画C++类图
  5. wps怎么统一修改标点符号_毕业论文的参考文献怎么加入??脚注如何降重?
  6. python datasets 下载_frds:金融学术研究数据的Python库
  7. 【284天】每日项目总结系列022(2017.11.16)
  8. xamarin android 设备,【Xamarin.Android】在Visual Studio中增强设备日志记录
  9. 书生中学计算机应用自费,浙江省台州市书生中学2016-2017学年高二上学期期中考试信息试题 Word版含答案.doc...
  10. android开发下载文件损坏解决方法,Android中已下载的.apk文件已损坏
  11. IEEE 802.15.4的信道接入机制一基础、信标和非信标帧网络
  12. sort(()=>{return Math.random()-0.5)}乱序数组不准确
  13. cdr转换成html格式,cdr生成对象
  14. halcon修改图像的灰度值
  15. HTML之调色原理分析
  16. [Halcon] license分享 — 2022.12月(持续更新)
  17. android 动态修改dns,如何修改android手机上网DNS
  18. 2020秋季甲级PAT 7-4 Professional Ability Test (30 分)
  19. css 实现鼠标悬浮时等比放大图片,鼠标移出时还原图片
  20. linux 负载高 cpu低,Linux服务器CPU使用率较低但负载较高

热门文章

  1. 《AngularJS深度剖析与最佳实践》一2.6 指令
  2. 58同城架构师谈:亿级流量架构演进
  3. 华硕笔记本bios U盘启动问题
  4. ps里html在哪,PS中的路径面板的使用教程
  5. PHP+MYSQL实现个人博客网站,PHP动态网页设计
  6. 国内哪一家银行的账户最适合用来接收来自国外机构的美元汇款?
  7. 怎样计算两个时间之间的间隔
  8. 雷军:别轻易尝试,要做好准备再去创业
  9. 劝人学医,天打雷劈?给医学新生的 10 条入学建议
  10. 解决 Flutter 在 iOS 模拟器中运行卡住问题