1. 介绍 promise 和模仿 Promise.all 和 Promise.race
promise 的设计主要是解决回调地狱 (接收结果用回调函数来处理, 但必须传入回调函数) 的问题, 由一层层嵌套回调函数改为由 then 来执行.
例如:
- // callback 用于接收返回结果, 异步方式
- fs.readFile("filePath", callback);
- // 还有一种方式
- cosnt {
- promises: fs
- } = require("fs"); // 用 promise 包装 fs 模块, 已经实现
- fs.readFile("filePath").then(callback);
- // 由上可看出, promise 只是解决了回调函数的调用方式, 没有彻底改变回调函数继续存在的问题.
promise 有三个状态, 分别是 pending, resolve,reject. 只有 resolve 或者 reject 被调用, 才会结束.
promise 对象可以通过 new 创建, 结果返回后 then 和 catch 方法会调用, resolve 和 reject 会走 then 方法, catch 是捕捉未处理异常的方法(比如: 500,404 之类).
值得注意的是, then 方法的返回值为 promise 类型, 如果在 then 中继续执行异步操作, 则可以在 then 后面再次写一个 then 操作. 叫做链式调用, 例如:
- Promise.resolve("success")
- .then((res) => "异步操作")
- .then((resSecond) => console.log(resSecond)); // resSecond 为 "异步操作"
另外可直接调用 resolve 状态或者 reject 状态, 例如 Promise.resolve(), 或者 Promise.reject()方法. 这两个方法直接返回结果, 也可以传入一个 Promise 对象或者工厂函数. 这两个函数本质都是内部创建了一个 Promise 对象, 调用 resolve 或者 reject.
现如今很多的异步请求, 异步执行方式, 都在向 promise 靠拢. 提供了很多的便利性. 比如: axios, 上面提到的 fs 模块, 等等. 我用过 angular 的 subscribe, 也是对异步的一种处理方式. 但有点不伦不类.
1.1 模拟异步操作, 用于测试
- // 模拟异步请求
- const suc = function (time: number) {
- return new Promise(resolve => {
- setTimeout(() => {
- // time 秒钟之后返回结果
- resolve("success");
- }, time);
- })
- }
- const rej = function (time: number) {
- return new Promise((resolve, reject) => {
- setTimeout(() => {
- // time 秒之后拒绝
- reject("fail");
- }, time);
- })
- }
- // 以上代码也可合并为一个函数, 请读者自行考虑.
1.2 Promise 的 all,race 方法模拟
PromiseAll 方法内内只接受两个异步 Promise, 算是简化版了(官网 API 代码简介 https://www.promisejs.org/api/ ), 能力有限. PromiseRace 基本和官网上的差不多.
PromiseRace: 竞争性关系, 获取第一个结果(无论结果 resolve 或者 reject), 立即返回.
PromiseAll_2: 感觉使用状态控制这种不是太好啊
- // 准确来说, 这个方法有缺陷, 只要第一个返回, 不管对与不对都返回, 应该是所有结果都被 reject 掉才会返回 reject, 只有一个正确都要返回正确结果. 可结合 PromiseAll_2 看
- function PromiseRace(arrs: Array): Promise<{}> {
- if (arrs.length === 0) return Promise.resolve([]);
- return new Promise((resolve, reject)=> {
- arrs.forEach((pro) => {
- Promise.resolve(pro).then(resolve, reject);
- });
- });
- }
- // 当所有结果为 ture, 才会返回 ture
- function isAllFulfilled(states: Array): boolean {
- let res: boolean = true;
- states.forEach(state => res = res && state)
- return res;
- }
- // 用一种循环的方式迭代每个异步方法, 如果不是函数或对象就直接作为结果返回
- function PromiseAll_2(arrs: Array): Promise<{}> {
- if (arrs.length === 0) return Promise.resolve([]);
- const states: Array = Array.from({length: arrs.length}, (item) => item = false);
- return new Promise((resolve, reject)=> {
- const result = [];
- arrs.forEach((pro, index) => {
- // 对输入做一个封装, 如果是常数或者不是 promise 的这样就直接返回
- Promise.resolve(pro).then(res => {
- states[index] = true;
- result[index] = res;
- if (isAllFulfilled(states)) resolve(result);
- }, err => reject(err));
- });
- });
- }
- function PromiseAll(one: Promise, two: Promise): Promise<{}> {
- return new Promise((resolve, reject) => {
- let twoRes = null;
- let oneRes = null;
- // 基于两个异步互相检测, 官网那个有点看不大明白. 各位有什么好的代码建议不妨评论说一下
- one.then((res) => {
- oneRes = res;
- if (twoRes) resolve([oneRes, twoRes]);
- }, (err) => reject(err));
- two.then((res) => {
- twoRes = res;
- if (oneRes) resolve([oneRes, twoRes]);
- }, (err) => reject(err));
- });
- }
- PromiseAll(suc(1000), rej(2000)).then((res) => {
- console.log(res);
- }).catch((err) => console.log(err));
1.3 小工具.
使用 promisify 对 settimeout 做个封装, 单纯只是延迟执行
- const util = require("util");
- // 封装 settimeout 延迟执行
- const delay = util.promisify(setTimeout); // 用作延迟执行, 一般在 await 的时候用
用例:
- async function test() {
- await delay(1000); // 延迟一秒执行
- }
async 简单介绍
async 彻底解决了异步操作回调函数问题.
只需使用 await 关键字, 就会等待异步操作执行完毕才会继续执行后续代码. 把异步操作
变为同步操作.
- // 代码
- async function test() {
- const {
- data
- } = await axios.get("http://www.baidu.com"); // {
- data
- }为解构赋值
- // do something
- }
- // 不用 async
- function test() {
- axios.get("http://www.baidu.com").then((res) => {
- console.log(res.data);
- //do something
- });
- }
- // 对比以上结构, async 函数的同步会带来很大的方便, 但在加载网页的时候可能需要等待.
- // 如果不希望页面卡顿, 采用异步还是比较好的.
2. 每周分享
前端框架和 es 的一些变化 https://juejin.im/post/5c88bf06f265da2dd37c5c9e , 这里面介绍的是前端中最近的一些框架或者基础性知识.
nginx 的基础入门 https://juejin.im/entry/58eda648a22b9d006347a706 , 对 nginx 的一个用法基本介绍.
阿里 AI labs 研发 "智能防骚扰电话技术", 当接听到骚扰电话时, 可以转到机器人接听. 我试了一下, 听得我一愣一愣的, 还以为真的和人工客服聊天. 具体想体验的可以在支付宝搜索天猫精灵. 不过这项功能可能会给你带来困扰, 如果你主动挂断电话, 就会立马改为由智能机器人接听, 如果是你女票打来的, 你有事情马上挂断, 后果不堪设想! 好在可以关闭或者打开. 玩玩可以, 可不要贪杯啊.(>_<)
----
资料
MDN, 关于 peomise 的解析
官网 API 代码简介 https://www.promisejs.org/api/
来源: https://www.cnblogs.com/zanzg/p/10566081.html