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的内部应该执行它
}
}
至于resolve
和reject
到底要做什么呢?我们先按下不表.
我们先来看看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