粥里有勺糖

vuePress-theme-reco 粥里有勺糖    2018 - 2023
粥里有勺糖 粥里有勺糖

Choose mode

  • dark
  • auto
  • light
关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
author-avatar

粥里有勺糖

285

文章

40

标签

关于我
备战春秋
  • 心得总结
  • 校招考点汇总
  • 面经汇总
  • 复习自查
技术笔记
  • 技术教程
  • 模板工程
  • 源码学习
  • 技术概念
  • 个人作品
  • 学习笔记
计算机基础
  • 算法与数据结构
  • 操作系统
  • 计算机网络
  • 设计模式
  • 剑指offer
大前端
  • javascript
  • vue
  • html
  • css
  • 🌏浏览器专题
  • Web性能优化
  • regexp
  • node
面试
  • 问解
  • javascript
  • css
  • 手撕代码
  • 性能优化
  • 综合问题
  • 面经汇总
  • 小程序
手撕代码
  • 数据结构与算法
  • javascript
  • css
个人站点
  • GitHub (opens new window)
  • 博客园 (opens new window)
  • 掘金 (opens new window)
线上作品
  • 轻取(文件收集) (opens new window)
  • 个人图床 (opens new window)
  • 考勤小程序 (opens new window)
  • 时光恋人 (opens new window)
  • 在线简历生成 (opens new window)
留言板
Github (opens new window)
  • Javascript

    • 简介
    • 获取某年某月的天数
    • 日期格式化
    • 展开多级数组
    • 判断数据类型的方案
    • 文件上传与下载
    • 柯里化
    • 闭包
    • delete
    • 垃圾回收
    • 节流与防抖
    • apply,call,bind
    • blob与file
    • Event Loop
    • Promise
    • 定时器
    • 原型与原型链
    • 作用域
    • 执行上下文栈
    • 变量对象
    • 作用域链
    • ECMAScript规范解读this
    • 执行上下文
    • 参数按值传递
    • 类数组与arguments
    • 浮点数
    • Symbol的用法
    • 箭头函数
    • 类型转换
    • 获取dom元素的方式
    • 浅拷贝与深拷贝
    • ES6+的新语法糖和方法整理
    • 学习过程中学到的一些取巧之法

Promise

vuePress-theme-reco 粥里有勺糖    2018 - 2023

Promise

粥里有勺糖 2020-04-14 大前端javascript

# Promise

Promise/A+ 规范 (opens new window)

# 手动实现简易版

const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'

function myPromise(fn) {
    this.state = PENDING
    this.value = null
    this.resolveFuns = []
    this.rejectFuns = []

    const resolved = (v) => {
        setTimeout(() => {
            if (this.state === PENDING) {
                this.state = RESOLVED
                this.value = v
                this.resolveFuns.forEach(fun => fun(this.value))
            }
        }, 0)
    }

    const rejected = (err) => {
        setTimeout(() => {
            if (this.state === PENDING) {
                this.state = REJECTED
                this.value = err
                this.rejectFuns.forEach(fun => fun(this.value))
            }
        }, 0)
    }

    try {
        fn(resolved, rejected)
    } catch (err) {
        rejected(err)
    }
}

myPromise.prototype.then = function (resolveFun, rejectFun) {
    resolveFun = typeof resolveFun === 'function' ? resolveFun : v => v
    rejectFun = typeof rejectFun === 'function' ? rejectFun : err => {
        throw err
    }

    if (this.state === PENDING) {
        this.resolveFuns.push(resolveFun)
        this.rejectFuns.push(rejectFun)
    }

    if (this.state === resolveFun) {
        resolveFun(this.value)
    }

    if (this.state === rejectFun) {
        rejectFun(this.value)
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

使用示例

new myPromise((resolve, reject) => {
    console.log('123') // 123
    // resolve(666)
    reject(777)
}).then(res => {
    console.log('success:' + res) // 666
}, err => {
    console.log('error:' + err) // 777
})
1
2
3
4
5
6
7
8
9

# 符合A+规范

const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'

function myPromise(fn) {
    this.state = PENDING
    this.value = null
    this.resolveFuns = []
    this.rejectFuns = []

    const resolved = (v) => {
        if (v instanceof myPromise) {
            return v.then(resolved, rejected)
        }
        setTimeout(() => {
            if (this.state === PENDING) {
                this.state = RESOLVED
                this.value = v
                this.resolveFuns.forEach(fun => fun(this.value))
            }
        }, 0)
    }

    const rejected = (err) => {
        setTimeout(() => {
            if (this.state === PENDING) {
                this.state = REJECTED
                this.value = err
                this.rejectFuns.forEach(fun => fun(this.value))
            }
        }, 0)
    }

    try {
        fn(resolved, rejected)
    } catch (err) {
        rejected(err)
    }
}

function resolutionProcedure(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('Error'))
    }
    if (x instanceof MyPromise) {
        x.then(function (value) {
            resolutionProcedure(promise2, value, resolve, reject)
        }, reject)
    }
    let called = false
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            let then = x.then
            if (typeof then === 'function') {
                then.call(
                    x,
                    y => {
                        if (called) return
                        called = true
                        resolutionProcedure(promise2, y, resolve, reject)
                    },
                    e => {
                        if (called) return
                        called = true
                        reject(e)
                    }
                )
            } else {
                resolve(x)
            }
        } catch (e) {
            if (called) return
            called = true
            reject(e)
        }
    } else {
        resolve(x)
    }
}

myPromise.prototype.then = function (resolveFun, rejectFun) {
    resolveFun = typeof resolveFun === 'function' ? resolveFun : v => v
    rejectFun = typeof rejectFun === 'function' ? rejectFun : err => {
        throw err
    }
    let that = this
    if (this.state === PENDING) {
        return (promise2 = new myPromise((resolve, reject) => {
            that.resolveFuns.push(() => {
                try {
                    const res = resolveFun(that.value)
                    resolutionProcedure(promise2, res, resolve, reject)
                } catch (err) {
                    reject(err)
                }
            })

            that.rejectFuns.push(() => {
                try {
                    const res = rejectFun(that.value)
                    resolutionProcedure(promise2, res, resolve, reject)
                } catch (err) {
                    reject(err)
                }
            })
        }))
    }

    if (this.state === RESOLVED) {
        return (promise2 = new myPromise((resolve, reject) => {
            setTimeout(() => {
                try {
                    const res = resolveFun(that.value)
                    resolutionProcedure(promise2, res, resolve, reject)
                } catch (err) {
                    reject(err)
                }
            }, 0)
        }))
    }

    if (this.state === REJECTED) {
        return (promise2 = new myPromise((resolve, reject) => {
            setTimeout(() => {
                try {
                    const res = rejectFun(this.value);
                    resolutionProcedure(promise2, res, resolve, reject)
                } catch (err) {
                    reject(err)
                }
            }, 0)
        }))
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

使用示例

new myPromise((resolve, reject) => {
    console.log('123')
    resolve(666)
    // reject(777)
}).then(res => {
    console.log('success:' + res)
}, err => {
    console.log('err:' + err)
})I
1
2
3
4
5
6
7
8
9
Edit this page (opens new window)
Last Updated: 2022/5/15 12:46:34