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

相关推荐
素界UI设计38 分钟前
建筑行业变革:用Three.js构建BIM数据可视化孪生平台
开发语言·javascript·信息可视化
青红光硫化黑1 小时前
React-native之组件
javascript·react native·react.js
菠萝+冰1 小时前
在 React 中,父子组件之间的通信(传参和传方法)
前端·javascript·react.js
庚云1 小时前
一套代码如何同时适配移动端和pc端
前端
Jinuss1 小时前
Vue3源码reactivity响应式篇Reflect和Proxy详解
前端·vue3
海天胜景1 小时前
vue3 el-select 默认选中第一个
前端·javascript·vue.js
小小怪下士_---_1 小时前
uniapp开发微信小程序自定义导航栏
前端·vue.js·微信小程序·小程序·uni-app
前端W1 小时前
腾讯地图组件使用说明文档
前端
页面魔术1 小时前
无虚拟dom怎么又流行起来了?
前端·javascript·vue.js
胡gh1 小时前
如何聊懒加载,只说个懒可不行
前端·react.js·面试