参考Promise 的  官方规范  https://promisesaplus.com/

Promise 其实就是一个状态机

它只有两种状态变化 pending    =》   fulfilled

         pending    =》   rejected

并且状态一旦发生变化后就不会再改变

我们用es5来实现下

先写个架子, 并测试下:

function myPromise(executor) {
var _this = this; // 保存当前的函数上下文
_this.status = 'pending'; // 初始状态
_this.resolveValue = null; // resolve初始值
_this.rejectValue = null; // reject初始值
function resolve(value) {
if (_this.status == 'pending') {
_this.status = 'Fulfilled';
_this.resolveValue = value;
}
}
function reject(reason) {
if (_this.status == 'pending') {
_this.status = 'Fulfilled';
_this.rejectValue = reason;
}
}
try { // 捕获错误
executor(resolve, reject)
} catch (e){
reject(e);
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
var _this = this;
if (_this.status == 'Fulfilled') {
onFulfilled(_this.resolveValue)
}
if (_this.status == 'Rejected') {
onRejected(_this.rejectValue)
}
}; var p = new myPromise((resolve, reject) => {
resolve('I am handsome');
throw Error('捕获错误')
});
p.then((data) => {
console.log(data)
}, (err) => {
console.log(err)
} );

结果:

它先执行resolve   状态 变为   Fulfilled    ,

然后报错 ,执行reject , 由于此时状态不是pending, 状态还是Fulfilled

Promise的核心是处理异步,

现在我们的代码并不能等待状态的改变,

接下来我们加上处理异步操作的功能, 并测试下

function myPromise(executor) {
var _this = this; // 保存当前的函数上下文
_this.status = 'pending'; // 初始状态
_this.resolveValue = null; // resolve初始值
_this.rejectValue = null; // reject初始值
_this.resolveCallbackList = []; // 存resolve的回调
_this.rejectCallbackList = []; // 存reject的回调
function resolve(value) {
if (_this.status == 'pending') {
_this.status = 'Fulfilled';
_this.resolveValue = value;
// 状态改变执行存的回调
_this.resolveCallbackList.forEach(function(ele){
if (ele) {
ele();
}
})
}
}
function reject(reason) {
if (_this.status == 'pending') {
_this.status = 'Rejected';
_this.rejectValue = reason;
// 状态改变执行存的回调
_this.rejectCallbackList.forEach(function(ele){
if (ele) {
ele();
}
})
}
}
try { // 捕获错误
executor(resolve, reject)
} catch (e){
reject(e);
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
var _this = this;
if (_this.status == 'Fulfilled') {
onFulfilled(_this.resolveValue)
}
if (_this.status == 'Rejected') {
onRejected(_this.rejectValue)
}
// 等待状态时把回调存起来,状态改变再触发
if (_this.status == 'pending') {
_this.resolveCallbackList.push(function () {
onFulfilled(_this.resolveValue)
});
_this.rejectCallbackList.push(function () {
onRejected(_this.rejectValue)
});
}
}; var p = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve('I am handsome');
}, 0);
// throw Error('捕获错误')
});
p.then((data) => {
console.log(data)
}, (err) => {
console.log(err)
} );

结果:

自己写一个Promise的更多相关文章

  1. 【原】手写一个promise

    上一篇文章中,我们介绍了Promise的基本使用,在这篇文章中,我们试着自己来写一个Promise,主要是学习Promise的内部机制,学习它的编程思想. !!!备注:本文写的不好,仅供自己学习之用, ...

  2. 掘金转载-手写一个Promise

    目录 一 什么是Promise ? 二 Promises/A+ 规范 2.1 术语 2.2 基本要求 2.2.1. Promise的状态 2.2.2. Then 方法 2.3 简易版实践 2.4 进一 ...

  3. 手写一个Promise/A+,完美通过官方872个测试用例

    前段时间我用两篇文章深入讲解了异步的概念和Event Loop的底层原理,然后还讲了一种自己实现异步的发布订阅模式: setTimeout和setImmediate到底谁先执行,本文让你彻底理解Eve ...

  4. 面试----你可以手写一个promise吗

    参考:https://www.jianshu.com/p/473cd754311f <!DOCTYPE html> <html> <head> <meta c ...

  5. 手写一个promise

    Promise A+ 规范:https://promisesaplus.com/ 注:以下代码没有通过 promises-aplus-tests 的全部测试,但基本功能还是全的( 测试结果: 864 ...

  6. 只会用就out了,手写一个符合规范的Promise

    Promise是什么 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise 是一个对象,从它可以获取异步操作的消息.Prom ...

  7. 一起学习造轮子(一):从零开始写一个符合Promises/A+规范的promise

    本文是一起学习造轮子系列的第一篇,本篇我们将从零开始写一个符合Promises/A+规范的promise,本系列文章将会选取一些前端比较经典的轮子进行源码分析,并且从零开始逐步实现,本系列将会学习Pr ...

  8. 请手写代码实现一个promise

    第一步:promise的声明 class Promise{ // 构造器 constructor(executor){ // 成功 let resolve = () => { }; // 失败 ...

  9. 操刀 requirejs,自己动手写一个

    前沿 写在文章的最前面 这篇文章讲的是,我怎么去写一个 requirejs . 去 github 上fork一下,顺便star~ requirejs,众所周知,是一个非常出名的js模块化工具,可以让你 ...

随机推荐

  1. Github网站css加载不出来的处理方法(转,亲测有效)

    转载链接:https://blog.csdn.net/qq_36589706/article/details/80573008因为工作需求,自己会经常使用到github,但是突然有一天打开github ...

  2. PHPExcel探索之旅---阶段一

    类似于Java,php也有操作Excel的方法,其中需要下载PHPExcel插件,将其中的Classes文件夹改名为PHPExcel并提取到根文件夹外面,将两个文件夹一起放在所需项目中 使用PHPEx ...

  3. Codeforces Round #129 (Div. 2) B

    Description The Little Elephant loves sortings. He has an array a consisting of n integers. Let's nu ...

  4. Angular学习笔记之组件之间的交互

    1.@Input:可设置属性 当它通过属性绑定的形式被绑定时,值会“流入”这个属性. 在子组件中使用,例如:@Input()name:string 父组件定义宾亮,并在父组件的模板中绑定,例如: 子组 ...

  5. Chapter13

    package scala /** * Created by EX-CHENZECHAO001 on 2018-04-04. */class Chapter13 { // 13 集合 // 所有的集合 ...

  6. GUI的最终选择 Tkinter(四):Entry、Listbox、Scrollbar和Scale组件

    Entry组件 Entry组件就是平时所说的输入框.输入框是程序员用到的最多的一个程序,例如在输入账号和密码的时候需要提供两个输入框,用于接收密码的输入框还会有星号将实际输入的内容隐藏起来. Tkin ...

  7. JSP标签和JSTL标签注意点

    1.转发和重定向问题 当前项目:/Test 转发路径:"/"根目录表示当前项目"/Test","/login.jsp"就是"/Te ...

  8. pat1081. Rational Sum (20)

    1081. Rational Sum (20) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Given N ...

  9. 用gethub下载ardupilot的最新源码

    1进入gethub的官方网站https://github.com/作者:恒久力行 QQ:624668529    在搜索框内输入ardupilot并点击搜索点回车       2会看到很多工程,选择那 ...

  10. thinkphp搜索实现

    视图: <html lang="zh-cn"><head> <meta charset="UTF-8"><title& ...