Promise(一)极简版demo

Promise(一)极简版demo

前言

在所有的编程语言中,异步处理都是一个绕不开的话题。而在JS的这个话题中,Promise则是当之无愧的主角之一,这应该是我们日常用的最多的异步API了。从今天开始将更新一些有关Promise的笔记。

异步逻辑

先来看一个异步操作:

ini 复制代码
setTimeout(() => {
    data = 'result';
    return data;
}, 1000);

显然这样是无法获取结果的,那如果我们将代码修改一下:

ini 复制代码
let result = setTimeout(() => {
    // 异步获取结果
    data = 'result';
    return data;
}, 1000);

JS的主线程是同步运行的,当代码运行到这里的时候,根据setTimeout的机制,返回值result的值是该定时器的ID。所以此处也无法获取值。既然已经联想到JS的机制了,或许我们可以考虑,使用变量赋值:

javascript 复制代码
let data = ''
setTimeout(() => {
    data = 'result';
}, 1000)
console.log(data); // ''
setTimeout(() => {
    console.log(data);
}, 1001); // 1001ms后,打印出来的结果是result

也就是说,变量赋值是有效的,只是如何抓住异步执行完的时机呢?毕竟我们没法估计实际的异步操作时间。

那么最好的办法就是把具体操作也放到异步逻辑中去,这样就可以利用JS的线性执行和任务队列来帮助我们抓住这个Timing:

ini 复制代码
setTimeout(() => {
    data = 'result';
    console.log(data);
}, 1000)
​
const handler = (data) => {}
setTimeout(() => {
    data = 'result';
    const handler = (data) => {}
}, 1000)

使用过Promise的我们会发现,这似乎很眼熟:

scss 复制代码
new Promise((resolve, reject) => {
    try {
        // 执行一个异步操作,成功
        const data = syncFunc();
        // 调用resolve传递返回值
        resolve(data);
    } catch (error) {
        // 失败
        reject(error)
    }
})

在Promise中我们也需要传入一个方法函数,只是这个函数中resolve, reject的实现对于使用者来说是黑盒。但起码我们知道为什么它这么要求了。

代码实现

scss 复制代码
class Promise {
    constructor(executor) {
        executor(resolve, reject) // 用户传入的executor通常都是异步的,在Promise的内部应该执行它
    }
}

至于resolvereject到底要做什么呢?我们先按下不表.

我们先来看看Promise A+规范的要求:

2.1 Promise state

A promise must be in one of three states: pending, fulfilled, or rejected.

2.1.1 When pengding, a promise may transition to fulfilled or rejected.

2.1.2 When fulfilled, must not transition, must have a value which must not change.

2.1.3 When rejected, must not transiton, must have a reason which must not change.

根据这部分说明,我们进一步更新代码:

ini 复制代码
const PENDING = 'PENDING';     // 等待态
const FULFILLED = 'DULFILLED'; // 成功态
const REJECTED = 'REJECTED';   // 失败态
class Promise {
    constructor() {
        this.state = PENDING;
        this.value = '';
        this.reason ='';
    }
}

完成这些定义后,我们还缺少一些相关的状态转化的实现,这就是resolve、reject要做的了

ini 复制代码
class Promise {
    constructor(executor) {
        this.state = PENDING;
        this.value = '';
        this.reason ='';
​
        const resolve = (value) => { // 成功时传入值
            this.state = FULFILLED;
            this.value = value;
        }
        const reject = (error) => {
            this.state = REJECTED;
            this.reason = error;
        }
        
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
        
    }
}

这样我们就完成了上述的内容,它既符合异步处理的思想,也符合Promise的实际运行逻辑、Promise A+规范的要求

结语

下一篇我们继续实现Promise

相关推荐
万少14 分钟前
使用Trae轻松安装openclaw的教程-附带免费token
前端·openai·ai编程
颜酱30 分钟前
一步步实现字符串计算器:从「转整数」到「带括号与优化」
javascript·后端·算法
浪浪山_大橙子30 分钟前
OpenClaw 十分钟快速,安装与接入完全指南 - 推荐使用trae 官方 skills 安装
前端·人工智能
忆江南34 分钟前
iOS 可视化埋点与无痕埋点详解
前端
离开地球表面_9935 分钟前
金三银四程序员跳槽指南:从简历到面试再到 Offer 的全流程准备
前端·后端·面试
_柳青杨37 分钟前
跨域获取 iframe 选中文本?自己写个代理中间层,再也不求后端!
前端
比尔盖茨的大脑37 分钟前
事件循环底层原理:从 V8 引擎到浏览器实现
前端·javascript·面试
天才熊猫君37 分钟前
Vue3 命令式弹窗原理和 provide/inject 隔离机制详解
前端
bluceli38 分钟前
Vue 3 Composition API深度解析:构建可复用逻辑的终极方案
前端·vue.js
程序员ys40 分钟前
前端权限控制设计
前端·vue.js·react.js