JavaScript深入理解-Promise以及常用方法详解
Promise
Promise 介绍
Promise 对象表示一个异步操作的最终完成(或失败)及其结果值。
状态:
一个 promise 必然处于以下几种状态之一
- 待定:初始状态(pending)
- 已兑现:操作成功完成(fulfilled)
- 已拒绝:操作失败(reject)
创建 Promise
Promise 对象是由关键字 new 及其构造函数来创建的。该构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数——resolve 和 reject ——作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用 reject 函数。
new Promise((resolve, reject) => {
  //处理操作  返回resolve或者reject
  if (flag) resolve(data);
  eles(reject(data));
});
需要某个自定义的函数,变成 Promise 只需返回一个 Promise 即可
function myFun(flag) {
  return new Promise((resolve, reject) => {
    //处理操作  返回resolve或者reject
    if (flag) resolve(data);
    eles(reject(errorData));
  });
}
在具体项目中,使用 Promise 封装获取当前配置方法。
/**
 * 获取字典列表
 * axios : axios
 * lang : 当前传入语言 ,根据不同语言,获取配置不同
 *
 * 判断sessionStorage里是否获取到当前所需要字典配置。
 * 如果有返回该配置,获取不到再从接口中获取数据,并保存到sessionStorage。
 */
function getDictionary(axios, lang) {
  // 查看sessionStorage
  const dic = sessionStorage.getItem("dictionary_data_" + lang) || null;
  // 返回一个Promise对象
  return new Promise((resolve, reject) => {
    if (dic) resolve(JSON.parse(dic));
    else {
      axios
        .get(`/api/dictionary?language=${lang}`)
        .then((res) => {
          const dic_data = {};
          if (res.data.code === 0 && res.data.result) {
            res.data.result.forEach((r) => (dic_data[r.itemName] = r));
            //存放sessionStorage
            sessionStorage.setItem(
              "dictionary_data_" + lang,
              JSON.stringify(dic_data)
            );
            // 返回数据
            resolve(dic_data);
          } else reject();
        })
        .catch((error) => reject());
    }
  });
}
静态方法
Primise.all(iterable)
传参需要是一个可迭代对象
Promise.all 返回一个 Promise 对象。
该 Promise 对象会在 Promise.all 的 iterable 参数对象里的所有 Promise 对象都成功才会触发。
简单来说就是只有 Promise.all 参数里的所有 Promise 成功才会触发,有一个失败就不会触发。
例如:
var promise1 = Promise.resolve("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([1, 2, 3]);
  }, 2000);
});
Promise.all([promise1, promise2, promise3]).then((res) => {
  console.log(res);
});
上面代码 会在大约两秒之后 打印输出 [ 'heihei', 'wenbo', [ 1, 2, 3 ] ]
因为 Promise.all 需要等待 promise3 中的 setTimeout 完成后才会触发返回 Promise 对象
又例如:
var promise1 = Promise.reject("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([1, 2, 3]);
  }, 2000);
});
Promise.all([promise1, promise2, promise3])
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e);
  });
上面代码,并不会在等待 2 秒左右输出[ 'heihei', 'wenbo', [ 1, 2, 3 ] ],而会直接输出heihei因为在 promise1 中返回的是一个 reject,Promise.all认为promise1失败(rejected)。Promise.all会异步的将失败的结果返回,而不管其它 promise 是否完成。
在某些特定的场合,需要 Promise.all 返回的数据,才让继续执行代码。因为Promise.all是异步的,我们可以借助 async 与 await 实现。
var promise1 = Promise.resolve("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([1, 2, 3]);
  }, 2000);
});
function demo() {
  Promise.all([promise1, promise2, promise3]).then((res) => {
    console.log(res);
  });
  console.log("heihei");
}
demo();
以上代码会在执行之后 先打印"heihei",之后 2 秒左右才会打印输出[ 'heihei', 'wenbo', [ 1, 2, 3 ] ]
var promise1 = Promise.resolve("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([1, 2, 3]);
  }, 2000);
});
async function demo() {
  await Promise.all([promise1, promise2, promise3]).then((res) => {
    console.log(res);
  });
  console.log("heihei");
}
demo();
上方在使用了 async 和 await之后 会等在 Promise.all 执行完成之后才会打印输出heihei。在实际项目中可以在下面使用Promise.all返回的数据进行操作。
Promise.allSettled(iterable)
传参需要是一个可迭代对象
Promise.allSettled 返回一个 Promise 对象。
该 Promise 对象会在 Promise.allSettled 的 iterable 参数对象里的所有 Promise 对象都成功或者失败才会触发。
简单说就是等所有的 Promise 执行完成才会触发,无论成功还是失败。
var promise1 = Promise.reject("heihei");
var promise2 = "wenbo";
var promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([1, 2, 3]);
  }, 2000);
});
Promise.allSettled([promise1, promise2, promise3])
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e);
  });
输出为:
[
  { status: "rejected", reason: "heihei" },
  { status: "fulfilled", value: "wenbo" },
  { status: "fulfilled", value: [1, 2, 3] },
];
可以看到Promise.allSettled的返回值为一个数组,数组里包括每个 Promise 的状态status,返回值value,和 rejected 的值reason
和Promise.all() 相比,Promise.all() 更适合彼此相互依赖或者在其中任何一个 reject 时立即结束。
Promise.any(iterable)
传参需要是一个可迭代对象
Promise.any 返回一个 Promise 对象。
接收一个 Promise 对象的集合,当其中的一个 promise 成功,就返回那个成功的 promise 的值。
var promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([4000]);
  }, 4000);
});
var promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([1000]);
  }, 1000);
});
Promise.any([promise1, promise2])
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e);
  });
简单来说, Promise.any 像是竞速模式,那个 Promise 先成功,就返回哪一个 Promise
Promise.any 和 Promise.all 是相反的,一个是全部成功才触发,一个只要有一个成功就触发。
var promise1 = Promise.reject("error");
var promise2 = Promise.reject("error2");
Promise.any([promise1, promise2])
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e);
  });
//输出
//AggregateError: All promises were rejected
如上代码,当所有 Promise 都没有成功时,将返回一个 Error 的 Promise
Promise.race(iterable)
传参需要是一个可迭代对象
Promise.any 返回一个 Promise 对象。
接收一个 Promise 对象的集合,当其中的一个 promise 成功或者失败时,就返回那个成功或者失败的 promise 的值。
和 Promise.any 对比,Promise.any 为当有一个成功时,返回成功的 promise,Promise.race 则是不论成功失败都返回
var promise1 = Promise.resolve("resolve");
var promise2 = Promise.reject("error");
Promise.race([promise1, promise2])
  .then((res) => {
    console.log(res); //resolve
  })
  .catch((e) => {
    console.log(e);
  });
// 输出为resolve
var promise1 = Promise.reject("error");
var promise2 = Promise.resolve("resolve");
Promise.race([promise1, promise2])
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e); //error
  });
//输出为 error
Promise.reject(reason)
返回一个状态为失败的 Promise 对象,并将给定的失败信息传递给对应的处理方法
Promise.reject()方法返回一个带有拒绝原因的 Promise 对象。
Promise.reject("test-reject")
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e); //test-reject
  });
Promise.resolve(value)
返回一个状态由给定 value 决定的 Promise 对象
如果这个是一个 Promise 对象,则返回这 Promise 对象。
如果这个值是 thenable(即带有"then" 方法),返回的 promise 会“跟随”这个 thenable 的对象,采用它的最终状态
Promise.resolve("test-resolve")
  .then((res) => {
    console.log(res); //test-resolve
  })
  .catch((e) => {
    console.log(e);
  });
当 Resolve 是一个 Promise 对象,则返回这个 Promise 对象。
var promise = Promise.resolve({
  name: "resolve",
});
Promise.resolve(promise)
  .then((res) => {
    console.log(res); //{name:resolve}
  })
  .catch((e) => {
    console.log(e);
  });
//reject情况
var promise = Promise.reject({
  name: "reject",
});
Promise.resolve(promise)
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e); //{name:reject}
  });
当 Resolve 是一个 thenable 对象时
var p1 = Promise.resolve({
  then: function (resolve, reject) {
    resolve("hello ~!");
  },
});
p1.then((res) => {
  console.log(res); //hello ~!
});
注意:要在解析为自身的 thenable 上调用 Promise.resolve。这将导致无限递归。
Promise 原型方法
Promise.prototype.catch(onRejected)
catch() 方法返回一个 Promise ,并且处理拒绝的情况
实际上 catch 的行为与调用 Promise.prototype.then(undefined, onRejected) 相同
obj.catch(onRejected) 内部 calls obj.then(undefined, onRejected)
var promise = new Promise((resolve, reject) => {
  throw "出现了错误~";
});
promise.then(
  (res) => {
    console.log(res);
  },
  (e) => {
    console.log(e); //出现了错误~
  }
);
promise
  .then((res) => {
    console.log(res);
  })
  .catch((e) => {
    console.log(e); //出现了错误~
  });
以上两种方法 都可以实现异常的捕获
Promise.prototype.then(onFulfilled, onRejected)
then() 方法返回一个 Promise。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。
当只穿一个值得时候默认是 Promise 成功的回调函数
//默认一个参数
var promise = new Promise((resolve, reject) => {
  resolve("成功~");
  //or
  // reject('失败~')
});
promise.then(
  (res) => {
    console.log(res); //成功~
  },
  (error) => {
    console.log(error); // 失败~
  }
);
Promise.prototype.finally(onFinally)
finally() 方法返回一个 Promise。在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行指定的回调函数。这为在 Promise 是否成功完成后都需要执行的代码提供了一种方式。
这避免了同样的语句需要在 then()和 catch()中各写一次的情况。
var promise = new Promise((resolve, reject) => {
  resolve("成功~");
  //or
  // reject('失败~')
});
promise
  .then(
    (res) => {
      console.log(res); //成功~
    },
    (error) => {
      console.log(error); // 失败~
    }
  )
  .finally((res) => {
    console.log("finally~");
  });
如以上代码所示,无论 Promise 返回 resolve 还是 reject,都会执行 finally 里的内容。
链式使用
由于 promise.then(),promise.catch() 和 promise.finally()可以对已完成(成功或者失败)的 Promise 进行操作,还会返回一个新的 Promise 对象,在新的 Promise 对象上我们还可以使用这些方法进行操作,形成一个链式操作。
var promise = new Promise((resolve, reject) => {
  resolve("成功~");
});
promise
  .then((res) => {
    console.log(res); //成功
    return new Promise((resolve, reject) => {
      resolve("成功01~");
    });
  })
  .then((res) => {
    console.log(res); //成功01~
    return new Promise((resolve, reject) => {
      resolve("成功02~");
    });
  })
  .then((res) => {
    console.log(res); //成功02~
    throw "error~";
  })
  .catch((e) => {
    console.log(e); //error~
  });
JavaScript深入理解-Promise以及常用方法详解的更多相关文章
- $.ajax()常用方法详解(推荐)
		AJAX 是一种与服务器交换数据的技术,可以在补充在整个页面的情况下更新网页的一部分.接下来通过本文给大家介绍ajax一些常用方法,大家有需要可以一起学习. 1.url: 要求为String类型的参数 ... 
- 转: javascript模块加载框架seajs详解
		javascript模块加载框架seajs详解 SeaJS是一个遵循commonJS规范的javascript模块加载框架,可以实现javascript的模块化开发和模块化加载(模块可按需加载或全部加 ... 
- javascript event(事件对象)详解
		javascript event(事件对象)详解 1. 事件对象 1. 事件对象 Event 对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 什 ... 
- JavaScript调试技巧之console.log()详解
		JavaScript调试技巧之console.log()详解 对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻 ... 
- JavaScript中的鼠标滚轮事件详解
		JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ... 
- 【Java】HashMap源码分析——常用方法详解
		上一篇介绍了HashMap的基本概念,这一篇着重介绍HasHMap中的一些常用方法:put()get()**resize()** 首先介绍resize()这个方法,在我看来这是HashMap中一个非常 ... 
- phpExcel常用方法详解【附有php导出excel加超级链接】
		phpExcel常用方法详解[附有php导出excel加超级链接] 发表于4年前(-- :) 阅读() | 评论() 0人收藏此文章, 我要收藏 赞0 http://www.codeplex.com/ ... 
- 《手把手教你》系列技巧篇(四十)-java+ selenium自动化测试-JavaScript的调用执行-下篇(详解教程)
		1.简介 在实际工作中,我们需要对处理的元素进行高亮显示,或者有时候为了看清楚做跟踪鼠标点击了哪些元素需要标记出来.今天宏哥就在这里把这种测试场景讲解和分享一下. 2.用法 创建一个执行 JS 的对象 ... 
- JavaScript进阶知识点——函数和对象详解
		JavaScript进阶知识点--函数和对象详解 我们在上期内容中学习了JavaScript的基本知识点,今天让我们更加深入地了解JavaScript JavaScript函数 JavaScript函 ... 
随机推荐
- Dart http库
			推荐下我写的一个http库ajanuw_http 最基本的获取数据 import 'package:http/http.dart' as http; main(List<String> a ... 
- 「NGK每日快讯」12.30日NGK第57期官方快讯!
- K8S线上集群排查,实测排查Node节点NotReady异常状态
			一,文章简述 大家好,本篇是个人的第 2 篇文章.是关于在之前项目中,k8s 线上集群中 Node 节点状态变成 NotReady 状态,导致整个 Node 节点中容器停止服务后的问题排查. 文章中所 ... 
- 将VMware虚拟机最小化到托盘栏
			版权:本文采用「署名-非商业性使用-相同方式共享 4.0 国际」知识共享许可协议进行许可. 目录 前言 将VMware最小化到托盘栏的方法 1.下载 Trayconizer 2.解压 trayco ... 
- Go的指针
			目录 指针 一.指针的声明 二.指针的默认值(Zero Value) 三.指针的解引用 四.向函数传递指针参数 1.非 数组/切片 指针传参 2.数组/切片 指针传参 五.Go不支持指针运算 指针 指 ... 
- 用 hexo 快速搭建博客
			如何做到一毛不拔的搭建网站 以下操作全程使用管理员权限,因为我不清楚哪里会出现 permission denied 1.下载 nodejs 对应 windows 用户,下载对应的 ".msi ... 
- MySQL:事务机制
			为什么需要事务处理? 在执行SQL语句的时候,某些业务要求,一系列操作必须全部执行,而不能仅执行一部分. MySQL5.0后引入了事务机制,MySQL支持几种基本的数据库引擎,并非所有引擎都支持事务处 ... 
- Mac创建Root用户
			1.打开Mac终端管理工具 前往-实用工具-终端 2.用命令的形式创建账户 sudo passwd root 3.输入当前登录用户密码 4.输入root用户密码并验证 
- 修改 Hosts 解决 Github 访问缓慢问题
			背景 最近访问 Github 经常出现访问速度慢的问题,甚至会出现无法连接的情况.有一天,在一次家常聊天中提到了这个事情,有一位热心的 Gitee 朋友就说:你改一下 Hosts 文件就可以了.修改了 ... 
- Python开发环境从零搭建-03-安装Python解释器并配置
			想要从零开始搭建一个Python的开发环境说容易也容易 说难也能难倒一片开发人员,在接下来的一系列视频中,会详细的讲解如何一步步搭建python的开发环境 本文章是搭建环境的第3篇 讲解的内容是:安装 ... 
