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

相关推荐
haogexiaole2 小时前
vue知识点总结
前端·javascript·vue.js
哆啦A梦15883 小时前
[前台小程序] 01 项目初始化
前端·vue.js·uni-app
智码看视界4 小时前
老梁聊全栈系列:(阶段一)架构思维与全局观
java·javascript·架构
小周同学@6 小时前
谈谈对this的理解
开发语言·前端·javascript
Wiktok6 小时前
Pyside6加载本地html文件并实现与Javascript进行通信
前端·javascript·html·pyside6
一只小风华~6 小时前
Vue:条件渲染 (Conditional Rendering)
前端·javascript·vue.js·typescript·前端框架
柯南二号6 小时前
【大前端】前端生成二维码
前端·二维码
程序员码歌7 小时前
明年35岁了,如何破局?说说心里话
android·前端·后端
博客zhu虎康7 小时前
React Hooks 报错?一招解决useState问题
前端·javascript·react.js
灰海8 小时前
vue中通过heatmap.js实现热力图(多个热力点)热区展示(带鼠标移入弹窗)
前端·javascript·vue.js·heatmap·heatmapjs