博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Promise使用
阅读量:4086 次
发布时间:2019-05-25

本文共 4296 字,大约阅读时间需要 14 分钟。

Promise是异步编程的一种解决方案,其他的异步编程解决方案还有—— 回调函数 、 事件监听、 发布订阅 ,以及ES6新增的 Generator 。

Promise的状态

  1. Pending(进行中)

  2. Resolved (已完成)

  3. Rejected (已失败)

Promise的特点

  1. 对象的状态不受外界影响。

  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。

Promise的用法

var promise = new Promise(function(resolve, reject) {  // ... some code  if (/* 异步操作成功 */){    resolve(value);  } else {    reject(error);  }});

注意:

resovle和reject函数都是由js引擎提供的函数不用自己定义。

其中 resovle 函数的作用是将 Promise 对象从 进行中 状态转换为 已完成 , reject 函数将 Promise 对象从进行中状态转换为 已失败 状态。

Promise.prototype.then()

Promise实例具有 then 方法,then方法是定义在原型对象 Promise.prototype 上的,它的作用是为 Promise 实例添加状态改变时的回调函数。

延续上面的代码:

promise.then(function(res) {    console.log(res)}, function(err) {    console.log(err)})

then对象接收两个回调函数作为参数,第一个回调函数是resovle的回调,第二个回调函数是reject的回调。即,一个用于处理状态为已完成的逻辑,另一个用于处理已失败的逻辑。

一个Ajax请求的例子:

var getJSON = function(url) {  var promise = new Promise(function(resolve, reject){    var client = new XMLHttpRequest();    client.open("GET", url);    client.onreadystatechange = handler;    client.responseType = "json";    client.setRequestHeader("Accept", "application/json");    client.send();    function handler() {      if (this.readyState !== 4) {        return;      }      if (this.status === 200) {        resolve(this.response);      } else {        reject(new Error(this.statusText));      }    };  });  return promise;};getJSON("/posts.json").then(function(json) {  console.log('Contents: ' + json);}, function(error) {  console.error('出错了', error);});

Promise.prototype.catch()

Promise.prototype.catch方法是 .then(null, rejection) 的别名,用于指定发生错误时的回调函数。不是指then方法的别名而是指resovle的回调函数为null的then方法的别名。

通常推荐使用catch方法来捕获异常,而不是使用reject的回调函数。

// 不推荐的写法promise  .then(function(data) {    // success  }, function(err) {    // error  });// 推荐的写法promise  .then(function(data) {    // success  })  .catch(function(err) {    // error  });

使用catch方法来接收错误信息的好处是, Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止 。所以一个catch可以捕获链式调用中多个Promise对象抛出的异常。

链式调用

当有几个异步操作需要链式调用时,promise是支持的。

一个简单的链式调用的例子:

getJSON("/post/1.json").then(function(post) {  return getJSON(post.commentURL);}).then(function funcA(comments) {  console.log("Resolved: ", comments);}, function funcB(err){  console.log("Rejected: ", err);});

Promise的then函数,返回的是一个新的Promise对象。如果返回的对象不是Promise对象会是什么效果呢?

以下是一些测验代码:

var promise = new Promise(function(resolve, reject) {  let a = '111';    resolve(a);});promise.then(function(res) {    return null;}).then(function(res){    console.log(res);}).catch(function(err) {    console.log(err);})// null
var b = function() {    console.log('bb');}var promise = new Promise(function(resolve, reject) {  let a = '111';    resolve(a);});promise.then(function(res) {    return b();}).then(function(res){    console.log(res);})// bb// undefined

可以看出,如果then retrun的不是一个Promise函数时,并不会报错,也没有抛出异常,相当于一个没有执行reject和resovle的Promise对象( 个人理解,有失偏颇。望自慎重,择善从之。 )。

Promise.all()

在某些时候,我们需要执行多个异步操作。这些异步操作可能有以下几种关系:

  1. 互不关联

  2. 逐个依赖

  3. 部分依赖

  4. 结果依赖(指需要获得所以返回的结果进行下一步的操作)

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。可以用来解决上面的4关系。

互不关联最好分开调用,部分依赖、逐个依赖用链式调用。

Promise.all接收一个Promise数组作为参数,即数组中的值都是Promise对象,如果不是就会先调用Promise.resovle方法,将参数转为Promise实例。

// 生成一个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对象都返回resovle时才会执行then方法,只要有一个Pormise对象返回的是reject,就执行catch。

ps: 还有Promise.race()方法,此方法和Promise.all()不同之处时,只要传入的Promise数组中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。可用于限制请求的最大反应时间。

const p = Promise.race([  fetch('/resource-that-may-take-a-while'),  new Promise(function (resolve, reject) {    setTimeout(() => reject(new Error('request timeout')), 5000)  })]);p.then(response => console.log(response));p.catch(error => console.log(error));// 如果超过5秒就返回请求超时

Promise.resolve()和Promise.reject()

这两个方法返回一个新的Promise实例,resovle方法返回的实例状态为resolve,同理reject方法返回reject。

都接收一个参数作为现有的对象,此参数可以为任何值包括null,undefined。

根据接收的参数,两种方法都会做出不同的处理。在此不做详细的介绍了,有兴趣的可以去看看

Promise.resolve('foo')// 等价于new Promise(resolve => resolve('foo'))

finally()

此方法用于最后执行,不Promise的状态如何,都会执行的操作(还有这种操作?)。在node中可用于关闭服务器或者数据库连接。在浏览器中可用于需要在异步函数返回之后执行的操作。

var p = new Promise(function(resovle.reject){    resovle('is resovle');});p.then(function(res) {    console.log(res) }).finally(function() {    console.log('is finally');})

转载地址:http://zfrni.baihongyu.com/

你可能感兴趣的文章
Java8 HashMap集合解析
查看>>
自定义 select 下拉框 多选插件
查看>>
Linux常用统计命令之wc
查看>>
fastcgi_param 详解
查看>>
搞定Java面试中的数据结构问题
查看>>
React Native(一):搭建开发环境、出Hello World
查看>>
Winform多线程
查看>>
Spring AOP + Redis + 注解实现redis 分布式锁
查看>>
poj 1976 A Mini Locomotive (dp 二维01背包)
查看>>
《软件过程管理》 第九章 软件过程的评估和改进
查看>>
《数据库系统概论》 第三章 关系数据库标准语言SQL
查看>>
《计算机网络》第五章 运输层 ——TCP和UDP 可靠传输原理 TCP流量控制 拥塞控制 连接管理
查看>>
二叉树深度优先遍历和广度优先遍历
查看>>
生产者消费者模型,循环队列实现
查看>>
获得github工程中的一个文件夹的方法
查看>>
《PostgreSQL技术内幕:查询优化深度探索》养成记
查看>>
PostgreSQL查询优化器详解之逻辑优化篇
查看>>
STM32中assert_param的使用
查看>>
为什么button在设置标题时要用一个方法,而不像lable一样直接用一个属性
查看>>
字符串的截取
查看>>