Promise 使用方法:https://www.runoob.com/w3cnote/javascript-promise-object.html

直接上代码,相关的解释都在代码的注释里面,这里以minPromise 代替 Promise:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body> <script type="text/javascript">
class minPromise {
/**
比如
var p = new minPromise ((resolve, reject)=> {
// 这里是处理的代码,脑补
})
那么 executor 就是 (resolve, reject) => { ... }
**/
constructor(executor){
// executor 必须是 function 类型
if (typeof executor !== 'function') {
throw new Error('Executor must be a function');
} // 初始状态是 PENDING
this.state = 'PENDING';
this.chained = []; const resolve = res => {
// 如果状态不是 PENDING 那就不进行处理了
if (this.state !== 'PENDING') {
return;
} // 假如说res这个对象有then的方法,我们就认为res是一个promise
if (res != null && typeof res.then === 'function') {
return res.then(resolve, reject);
} this.state = 'FULFILLED';
this.internalValue = res;
// 这里用到 解构 相当于 for(let item of this.chainer) 然后 { onFulfilled } = item , 下同
for (let { onFulfilled } of this.chained) {
onFulfilled(res);
}
}; const reject = err => {
if (this.state !== 'PENDING') {
return;
}
this.state = 'REJECTED';
this.internalValue = err;
for (const { onRejected } of this.chained) {
onRejected(err);
}
}; // 这里相当于函数初始运行 利用了构造函数自动执行的特性
try{
executor(resolve, reject);
}catch(err){
reject(err);
}
} // 状态是 FULFILLED 或者 REJECTED 说明已经执行完 resolve 方法, internalValue 也已经有值了,可以直接执行
// 状态是 PENDING 说明 resolve 的方法是异步的, 就先把 onFulfilled, onRejected 事件放到 chained 里面,存起来,等 resolve 的时候在执行 // 如果不需要then的链式调用, 用这个then就可以
// then(onFulfilled, onRejected) {
// if (this.state === 'FULFILLED') {
// onFulfilled(this.internalValue);
// } else if (this.state === 'REJECTED') {
// onRejected(this.internalValue);
// } else {
// this.chained.push({ onFulfilled, onRejected });
// }
// } // 需要then的链式调用的话 让then返回 Promise 就行
then(onFulfilled, onRejected) {
return new minPromise((resolve, reject) => {
// 这里把 onFulfilled onRejected 封装了下 是因为 resolve(onFulfilled(res)) 或者 reject(onRejected(err)) 执行的时候 有可能报错,做了错误兼容处理
const _onFulfilled = res => {
try {
//注意这里resolve有可能要处理的是一个promise
resolve(onFulfilled(res));
} catch (err) {
reject(err);
}
};
const _onRejected = err => {
try {
reject(onRejected(err));
} catch (_err) {
reject(_err);
}
};
if (this.state === 'FULFILLED') {
_onFulfilled(this.internalValue);
} else if (this.state === 'REJECTED') {
_onRejected(this.internalValue);
} else {
this.chained.push({ onFulfilled: _onFulfilled, onRejected: _onRejected });
}
});
},
// resolve方法 相当于返回一个Promise对象
resolve(value) {
return new minPromise(value => {
resolve(value);
})
},
reject(reason) {
return new minPromise((resolve, reject) => {
reject(reason);
});
},
// 全部成功的时候返回的是一个结果数组,失败的时候 会直返回失败
all(promiseArr) {
return new minPromise((res, rej) => {
// promiseArr 所有的值都看一下
var arr = [];
var times = 0;
processResult = (index, result) =>{
arr[index] = result;
times++;
// arr.length == promiseArr.length, 代表全部都 resolve 成功
if (times == promiseArr.length) {
// 在这里执行最后的 resolve
res(arr);
}
}; for (let i = 0; i < promiseArr.length; i++) {
var oPromise = promiseArr[i];
// 是 promise
if (typeof oPromise.then == 'function') {
oPromise.then((val) =>{
// then 成功后把值存下来
processResult(i, val)
}, (reason) =>{
// 不成功 直接 reject
rej(reason);
})
}else {
processResult(i, oPromise);
}
}
});
}, // 哪个实例获得结果最快,就返回那个结果,不管结果本身是成功还是失败;
race(promiseArr) {
return new minPromise((resolve, reject) => {
promiseArr.forEach((promise) => {
promise.then(resolve, reject);
});
});
}, } // 测试非链式调用
let p = new minPromise(resolve => {
setTimeout(() => resolve('Hello'), 100);
}); p.then(res => console.log(res)); p = new minPromise((resolve, reject) => {
setTimeout(() => reject(new Error('woops')), 100);
}); p.then(() => {}, err => console.log('Async error:', err.stack)); // 测试链式调用
let p2 = new minPromise(resolve => {
setTimeout(() => resolve('World'), 100);
}); p2.
then(res => new minPromise(resolve => resolve(`Hello, ${res}`))).
then(res => console.log(res)); </script> </body>
</html>

  参考:https://segmentfault.com/a/1190000014440641   ,https://juejin.im/post/5aa7868b6fb9a028dd4de672#heading-9

2020.3.11 新增:

all(promiseArr) {
let result = []
promiseArr.forEach((item, index) => { item.then(res => { result[index] = res i++ if(i === promiseArr.length) { resolve(result) } }, err => { reject(err) })
}
}

用es6实现一个promsie的更多相关文章

  1. 用es6写一个分数库

    es6发布后nodejs开始更新.最近写一些库发现新特性还是很好用的,于是回来写一个分数库练手. 对于es6本身 ... => 以及 array.includes 很简洁.class依然不是很顺 ...

  2. new.target元属性 | 分别用es5、es6 判断一个函数是否使用new操作符

    函数内部有两个方法 [[call]] 和 [[construct]] (箭头函数没有这个方法),当使用new 操作符时, 函数内部调用 [[construct]], 创建一个新实例,this指向这个实 ...

  3. es6声明一个类

    js语言的传统方式是通过定义构造函数,生成心得对象.是一种基于原型的面向对象系统.在es6中增加了class类的概念,可以使用class关键字来声明一个类.之后用这个类来实例化对象. 构造函数示例 c ...

  4. 用ES6创建一个简单工厂模式

    1 什么是工厂模式? 工厂模式是用来创建对象的一种最常用的设计模式.我们不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂.工厂模式根据抽象程度的不同可以分为:简 ...

  5. 不用循环,、es6创建一个长度为100的数组

    问题描述:在不使用循环的条件下,如何创建一个长度为100的数组,并且数组的每一个元素是该元素的下标? 结果为: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1 ...

  6. es6 封装一个登录注册的验证滑块

    1,需求分析 滑块从左滑到右,开始滑.结束滑两种状态.两种状态显示的内容和样式的不同. 这是淘宝注册验证滑块的示例图 2,代码分析 const render = Symbol('render') co ...

  7. es6 封装一个基础的表单验证

    1, 需求分析 设计一个通用的表单验证,如果后期表单中添加了更多的需求,不需要更改之前的代码逻辑,最好不要改之前的代码,需要加什么直接加就好了. 2,代码分析 此表单验证最好返回一个函数,在api设计 ...

  8. ES6 自定义一个实现了Iterator接口的对象

    参考资料 var obj = { data: [1,2,3,4,5], // 这里实际上就是去定义如何实现Iterator接口 [Symbol.iterator](){ const that = th ...

  9. 深入浅出ES6教程『async函数』

    大家好,本人名叫苏日俪格,大家叫我 (格格) 就好,在上一章节中我们学到了Symbol & generator的用法,下面我们一起来继续学习async函数: async [ə'zɪŋk]:这个 ...

随机推荐

  1. 玩转springcloud(一):什么是Springcloud ,有什么优缺点? 学习顺序是什么?

    一.首先看官方解释: Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线).分布式系统的协调导致了样板模式, 使 ...

  2. insmod: can't insert 'xxx.ko': unknown symbol in module, or unknown parameter

    手动加载内核模块时候,报如下错误信息 insmod: can't insert 'xxx.ko': unknown symbol in module, or unknown parameter 问题原 ...

  3. 记一次引用maven插件报错解决方法

    1.报错信息如图: plugin org.springframework.boot:spring-boot-maven-plugin not found 2.解决方案: maven的配置文件[sett ...

  4. pyltp安装

    第一步:下载wheel文件 第二步:进入该文件的文件夹 第三步:pip install wheel文件名 注意:python的安装版本必须和pyltp的版本相同,我这版本都是pyhton3.6.之前p ...

  5. java线程基础巩固---线程生命周期以及start方法源码剖析

    上篇中介绍了如何启动一个线程,通过调用start()方法才能创建并使用新线程,并且这个start()是非阻塞的,调用之后立马就返回的,实际上它是线程生命周期环节中的一种,所以这里阐述一下线程的一个完整 ...

  6. Webpack v4.8.3 快速入门指南

    一.进入 https://webpack.docschina.org/ 官方文档,点击 "文档" 进入 文档页面,文档中包含  “概念,配置,API,指南,LOADERS,插件&q ...

  7. service worker在移动端H5项目的应用

    1. PWA和Service Worker的关系 PWA (Progressive Web Apps) 不是一项技术,也不是一个框架,我们可以把她理解为一种模式,一种通过应用一些技术将 Web App ...

  8. 一文学会redis从零到入门

    本文参照视屏学习整理:https://www.bilibili.com/video/av16841549/?p=9 相关软件.资料: 基本条件:有虚拟机或相关linux系统,熟悉基本linux操作 本 ...

  9. node 中的global对象和process对象

    官方文档:http://nodejs.cn/api/ 因为Node.js是运行在服务区端的JavaScript环境,服务器程序和浏览器程序相比,最大的特点是没有浏览器的安全限制了,而且,服务器程序必须 ...

  10. element-ui练习使用总结

    <el-row> <el-col class="borderRed" :span="24"> <div class="g ...