Open whu12yz opened 5 years ago
function isFunc(func) { return Object.prototype.toString.call(func) === '[object Function]'; } function pureFunc(value) { return value; } function pureErrorFunc(err) { throw err; } function isNode() { return typeof process === 'object' && Object.prototype.toString.call(process) === '[object process]'; } function schedule(callback) { if (!isFunc(callback)) return; // 确保task 异步在microtask中执行 if(isNode()) { return process.nextTick(callback); } else if(typeof MutationObserver !== 'undefined') { const div = document.createElement('div'); const observer = new MutationObserver(() => { callback(); observer.disconnect(); }) observer.observe(div, {attributes: true}); div.classList.toggle('trigger') } else if (typeof setImmediate !== 'undefined') { setImmediate(calback); } else if (typeof setTimeout !== 'undefined') { setTimeout(callback); } } function resolvePromise(onResolved, value, resolve, reject) { schedule(() => { try{ const result = onResolved(value); if (result instanceof Promise) { result.then(resolve, reject); } else { resolve(result); } }catch(err) { reject(err); } }) } function rejectPromise(onRejected, value, resolve, reject) { schedule(() => { try{ const result = onRejected(value); if (result instanceof Promise) { result.then(resolve, reject); } else { resolve(result); } }catch(err) { reject(err); } }) } class Promise { constructor(excutor) { if (!isFunc(excutor)) { throw Error('new Promise param must be a function'); } this.status = 'PENDING'; this.data = '' this.resolveCallbackList = []; //promise结束之前可能会有多可回调添加上去 this.rejectCallbackList = []; //同理 const resolve = (value) => { if (this.status === 'PENDING') { this.status = 'RESOLVED'; this.data = value; this.resolveCallbackList.forEach((onResolve) => { schedule(() => { onResolve(this.data); }) }) } } const reject = (reason) => { if (this.status === 'PENDING') { this.status = 'REJECTED'; this.data = reason; this.rejectCallbackList.forEach((onReject) => { schedule(() => { onReject(this.data); }) }) } } try{ excutor(resolve, reject); }catch(err) { reject(err); } } static resolve(value) { return new Promise((resolve, reject) => { resolve(value); }); } static reject(err) { return new Promise((resolve, reject) => { reject(err); }); } then (onResolved, onRejected) { onResolved = isFunc(onResolved) ? onResolved : pureFunc; onRejected = isFunc(onRejected) ? onRejected : pureErrorFunc; if (this.status === 'PENDING') { return new Promise((resolve, reject) => { this.resolveCallbackList.push((value) => { resolvePromise(onResolved, value, resolve, reject); }); this.rejectCallbackList.push((value) => { rejectPromise(onRejected, value, resolve, reject); }) }) } if ( this.status === 'RESOLVED') { return new Promise((resolve, reject) => { resolvePromise(onResolved, this.data, resolve, reject); }) } if ( this.status === 'REJECTED') { return new Promise((resolve, reject) => { rejectPromise(onRejected, this.data, resolve, reject); }) } } catch(onRejected) { return this.then(null, onRejected); } } module.exports = Promise;
第一个版本用了Object.observe去实现异步,在microTask中执行。大部分浏览器都已经废弃此方法,现已在所有降级方案中去掉Object.observe.