从零实现Promise
APromise
遵循Promises/A+规范,拥有ES6.Promise
的主要api,使用了setTimeout
模拟异步机制。
实现过程可以看到 链式调用,reject向下传播,及各个api 方法的意义。
代码实现
const identity = val => val;
const isFunction = func => typeof func === "function";
const State = {
pending: "pending",
resolved: "resolved",
rejected: "rejected"
};
export default class APromise {
constructor(fn) {
// 初始化状态
this.promiseState = State.pending;
this.promiseValue = undefined;
// 处理器数组
this.hanlders = [];
this.resolve = value => {
return this.setResult(value, State.resolved, "resolve");
};
this.reject = reason => {
return this.setResult(reason, State.rejected);
};
this.setResult = (value, state, fromWhere) => {
const set = () => {
if (this.promiseState !== State.pending) {
return null;
}
if (value instanceof APromise && fromWhere === "resolve") {
// 是否resolve取决于传入的promise
return value.then(this.resolve, this.reject);
}
this.promiseState = state;
this.promiseValue = value;
return this.executeHandlers();
};
setTimeout(set);
};
this.executeHandlers = () => {
if (this.promiseState === State.pending) {
return null;
}
this.hanlders.forEach(handler => {
if (this.promiseState === State.resolved) {
handler.onResolved(this.promiseValue);
} else {
handler.onRejected(this.promiseValue);
}
});
// 每次执行完毕后清空
this.hanlders = [];
};
this.attachHandler = handler => {
this.hanlders = [...this.hanlders, handler];
this.executeHandlers();
};
try {
fn(this.resolve, this.reject);
} catch (e) {
this.reject(e);
}
}
then(onResolved, onRejected) {
onResolved = isFunction(onResolved) ? onResolved : identity;
return new APromise((resolve, reject) => {
this.attachHandler({
onResolved: value => {
try {
resolve(onResolved(value));
} catch (e) {
reject(e);
}
},
onRejected: reason => {
try {
isFunction(onRejected)
? resolve(onRejected(reason))
: reject(reason);
} catch (e) {
reject(e);
}
}
});
});
}
catch(onRejected) {
onRejected = isFunction(onRejected) ? onRejected : identity;
return this.then(identity, onRejected);
}
finally(fn) {
// finally保持promise最后的状态结果,与then不同
return new APromise((resolve, reject) => {
this.attachHandler({
onResolved: value => {
fn();
resolve(value);
},
onRejected: reason => {
fn();
reject(reason);
}
});
});
}
static resolve(v) {
return new APromise((resolve, reject) => {
return resolve(v);
});
}
static reject(v) {
return new APromise((resolve, reject) => {
return reject(v);
});
}
static all(arr) {
return new APromise(function(resolve, reject) {
var result = [],
i = arr.length;
arr.forEach(function(p, index) {
p.then(
function(data) {
result[index] = data;
i--;
if (i === 0) {
resolve(result);
}
},
function(error) {
reject(error);
}
);
});
});
}
static race(arr) {
return new APromise(function(resolve, reject) {
for (let p of arr.map(APromise.resolve)) {
p.then(
function(data) {
resolve(data);
},
function(error) {
reject(error);
}
);
}
});
}
}
参考链接
相关文章
- webpack相关知识
能够处理JS文件的互相依赖关系 能够处理JS的兼容问题 安装 全局安装 npm install webpack -g 项目安装 npm install webpack --save-
- Javascript基础和ES6
HTML的基础事件 onmouseover、onmouseout表示JS事件的鼠标移入鼠标移出 document.getElementById('id') JS中选择HTML的ID元素<in
- JavaScript编码规则
JavaScript编码规则 目的:改善协作编码、代码质量。 var 声明变量必须用var。 防止变量变为全局变量,污染全局环境。 常量 基本类型number、string、boolean是常量值。对
- JavaScript获取和设置CSS属性
获取样式 元素对象的宽高位置距离等属性 如offsetWidht、cilentWidht、scrollWidth…… let oWidth=obj.offsetWidth; 注意: 只能获取属
- javascript作用域、上下文、this和闭包详解
词法作用域lexical scope 定义在词法阶段的作用域。词法作用域是变量和语句块在定义时所处的位置决定的。 全局 块级:在{}之内是一个块级作用域(ES6之前没有块级作用于只有函数内的局部作用
随机推荐
- webpack相关知识
能够处理JS文件的互相依赖关系 能够处理JS的兼容问题 安装 全局安装 npm install webpack -g 项目安装 npm install webpack --save-
- Javascript基础和ES6
HTML的基础事件 onmouseover、onmouseout表示JS事件的鼠标移入鼠标移出 document.getElementById('id') JS中选择HTML的ID元素<in
- JavaScript编码规则
JavaScript编码规则 目的:改善协作编码、代码质量。 var 声明变量必须用var。 防止变量变为全局变量,污染全局环境。 常量 基本类型number、string、boolean是常量值。对
- JavaScript获取和设置CSS属性
获取样式 元素对象的宽高位置距离等属性 如offsetWidht、cilentWidht、scrollWidth…… let oWidth=obj.offsetWidth; 注意: 只能获取属
- javascript作用域、上下文、this和闭包详解
词法作用域lexical scope 定义在词法阶段的作用域。词法作用域是变量和语句块在定义时所处的位置决定的。 全局 块级:在{}之内是一个块级作用域(ES6之前没有块级作用于只有函数内的局部作用