当前位置:网站首页>手撸promise【二、Promise源码】【代码详细注释/测试案例完整】
手撸promise【二、Promise源码】【代码详细注释/测试案例完整】
2022-06-27 03:18:00 【翼遥bingo】
手撸Promise即完成promise的主要功能
- 声明构造函数
- resolve与reject
- throw抛出异常改变状态
- Promise的对象状态只能修改一次
- then方法执行回调
- 同步任务回调的执行
- 异步任务回调的执行
- 指定多个回调的实现
- 同步修改状态then方法结果返回
- 异步修改状态then方法结果返回
- Promise的API
- 构造函数: then,catch
- 函数对象: resolve,reject,all,race方法
一、 index.html
测试手撸的promise.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./promise.js"></script>
</head>
<body>
<script> let p = new Promise((resolve, reject) => {
resolve('OK'); // reject("error"); // throw "err"; setTimeout(() => {
// resolve('OK'); // reject('err'); // ............................抛出错误该咋办。。。。。。。。。。。。。。 // throw "err"; }, 1000); }); console.log(p); // p.then(value => {
// console.log(value); // }, reason => {
// console.warn(reason); // }) const res = p.then(value => {
// alert(value); return 'hello'; // return new Promise((resolve, reject) => {
// resolve("success"); // // reject("error"); // }) // throw "fail"; }, reason => {
alert(reason); }) console.log(res); let res2 = p.catch(reason => {
console.warn(reason); }) console.log(res2); // 异常穿透,值传递 p.then(value => {
// console.log(111); // throw '失败了' }).then(value => {
console.log(222); }).then(value => {
console.log(333); }).catch(reason => {
console.warn(reason); }) // resolve方法测试用例 const p1 = Promise.resolve('OK'); const p2 = Promise.resolve(new Promise((resolve, reject) => {
reject("errpr"); })); const p3 = Promise.resolve(Promise.resolve('Oh Yeah!')); console.log(p1); // reject测试用例 const r1 = Promise.reject('Error'); const r2 = Promise.reject(new Promise((resolve, reject) => {
resolve('ok') })) console.log(r1); console.log(r2); // 调用all方法 let a1 = new Promise((resolve, reject) => {
resolve('OK'); }) let a2 = Promise.resolve('Success'); let a3 = Promise.resolve('Oh Yeah'); let result3 = Promise.all([a1, a2, a3]); console.log(result3); // 调用race方法 let ra1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK'); }) }) let ra2 = Promise.reject('Successs'); let ra3 = Promise.resolve('Oh Yeah!') let result4 = Promise.race([ra1, ra2, ra3]); console.log(result4); // then方法回调的异步执行 let then1 = new Promise((resolve, reject) => {
resolve('OK'); console.log(111); }) then1.then(value => {
console.log(222); }) console.log(333); </script>
</body>
</html>
二、 promise.js
function Promise(executor) {
// 添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
// 生命属性
this.callbacks = [];
const self = this;
// resolve函数
function resolve(data) {
// Promise对象状态只能修改一次
if (self.PromiseState !== 'pending') return;
// 1. 修改对象的状态(promiseState)
self.PromiseState = 'fulfilled';
// 2. 设置对象结果值(promiseResult)
self.PromiseResult = data;
// 调用成功的回调函数
// if (self.callback.onResolved) {
// self.callback.onResolved(data);
// }
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(item);
})
})
}
// reject函数
function reject(data) {
if (self.PromiseState !== 'pending') return;
self.PromiseState = 'rejected';
self.PromiseResult = data;
// 调用失败的回调函数
// if (self.callback.onRejected) {
// self.callback.onRejected(data);
// }
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data);
})
})
}
try {
// 同步调用【执行器函数】
executor(resolve, reject);
} catch (e) {
// 修改Promise对象状态为失败
reject(e);
}
}
// 添加then方法
Promise.prototype.then = function(onResolved, onRejected) {
const self = this;
// 判断回调函数参数->异常穿透
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value;
// value => { return value; }
}
return new Promise((resolve, reject) => {
// 封装函数
function callback(type) {
try {
// 获取回调函数的执行结果
let result = type(self.PromiseResult);
// 判断
if (result instanceof Promise) {
// 如果是Promise类型的对象
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
// 结果的对象状态为成功
resolve(result);
}
} catch (e) {
reject(e);
}
}
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
callback(onResolved);
})
}
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected);
})
}
// 判断pending状态
if (this.PromiseState === 'pending') {
// 保存回调函数
this.callbacks.push({
onResolved: function() {
callback(onResolved);
},
onRejected: function() {
callback(onRejected);
}
})
}
})
}
// 添加 catch方法
Promise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected);
}
// 添加resolve方法
Promise.resolve = function(value) {
// 返回promise对象
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
resolve(value);
}
})
}
// 添加reject方法
Promise.reject = function(reason) {
return new Promise((resolve, reject) => {
reject(reason);
})
}
// 添加all方法
Promise.all = function(promises) {
// 返回结果为promise对象
return new Promise((resolve, reject) => {
// 声明变量
let count = 0;
let arr = [];
// 遍历
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
count++;
arr[i] = v;
if (count === promises.length) {
// 修改状态
resolve(arr);
}
}), r => {
reject(r);
}
}
})
}
// 添加 race 方法
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
// 修改返回对象的状态为[成功]
resolve(v);
}, r => {
reject(r);
})
}
})
}
三、 测试返回结果展示:


边栏推荐
- 解决cherry pick提交报错问题
- Enterprise digital transformation: informatization and digitalization
- 2021:Passage Retrieval for Outside-KnowledgeVisual Question Answering通道检索的外部知识视觉问答
- 人群模拟
- NestJS环境变量配置,解决如何在拦截器(interceptor)注入服务(service)的问题
- 2016Analyzing the Behavior of Visual Question Answering Models
- Pat grade a 1021 deep root
- Pat grade a 1018 public bike management
- GAMES101作业7提高-微表面材质的实现过程
- 2021:Beyond Question-Based Biases:Assessing Multimodal Shortcut Learning in Visual Question Answeri
猜你喜欢

Pat grade a 1026 table tennis

CVPR2021:Separating Skills and Concepts for Novel Visual Question Answering将技巧与概念分开的新视觉问答

pytorch_grad_cam——pytorch下的模型特征(Class Activation Mapping, CAM)可视化库

PAT甲级 1025 PAT Ranking

pytorch_ grad_ Cam -- visual Library of class activation mapping (CAM) under pytorch

Flink learning 3: data processing mode (stream batch)

Calculation of average wind direction and speed (unit vector method)

2021:Graphhopper: Multi-Hop Scene Graph Reasoning for Visual Question Answering

Learning Tai Chi Maker - mqtt (VII) advanced mqtt theme

Learn from Taiji Maker - mqtt Chapter 2 (I) QoS service quality level
随机推荐
Leetcode 785: judgment bipartite graph
servlet与JSP期末复习考点梳理 42问42答
PAT甲级 1024 Palindromic Number
2021:Graphhopper: Multi-Hop Scene Graph Reasoning for Visual Question Answering
Uni-app 之uParse 富文本解析 完美解析富文本!
Super detailed, 20000 word detailed explanation, thoroughly understand es!
Learn Tai Chi Maker - mqtt Chapter 2 (3) reserved messages
2021:AdaVQA: Overcoming Language Priors with Adapted Margin Cosine Loss∗自适应的边缘余弦损失解决语言先验
学习太极创客 — MQTT(六)ESP8266 发布 MQTT 消息
Paddlepaddle 20 implementation and use of exponentialmovingaverage (EMA) (support static graph and dynamic graph)
ESP8266
[array] sword finger offer II 012 The sum of left and right subarrays is equal | sword finger offer II 013 Sum of two dimensional submatrix
2021:adavqa: overlapping language priors with adapted margin cosine loss *
Solve the problem of error reporting in cherry pick submission
How does the brain do arithmetic? Both addition and subtraction methods have special neurons, and the symbol text can activate the same group of cell sub journals
Topolvm: kubernetes local persistence scheme based on LVM, capacity aware, dynamically create PV, and easily use local disk
How to solve the problem of low applet utilization
Flink学习5:工作原理
Pat class a 1024 palindromic number
Flink learning 4:flink technology stack