基础版Promise
const Promise = function Promise(executor) {
let self = this;
if (toType(executor) !== 'function') throw Error('Promise resolver ' + toType(executor) + ' is not a function');
if (!(self instanceof Promise)) throw new TypeError('undefined is not a promise');
self.state = 'pending';
self.value = undefined;
self.onfulfilledCallbacks = [];
self.onrejectedCabacks = [];
const change = function change(state, value) {
if (self.state !== 'pending') return;
self.state = state;
self.value = value;
setTimeout(() => {
var callbacks = self.state === 'fulfilled' ? self.onfulfilledCallbacks : self.onrejectedCabacks;
for (var i = 0; i < callbacks.length; i++) {
callbacks[i](self.value);
}
});
}
try {
executor(function (result) {
change('fulfilled', result);
}, function (reason) {
change('rejected', reason);
})
} catch (err) {
change('rejected', err.message);
}
return self
}
Promise.prototype = {
constructor: Promise,
then: function then(onfulfilled, onrejected) {
let self = this;
switch (self.state) {
case 'fulfilled':
setTimeout(() => {
onfulfilled(self.value);
});
break;
case 'rejected':
setTimeout(() => {
onrejected(self.value);
});
break;
default:
self.onfulfilledCallbacks.push(onfulfilled);
self.onrejectedCabacks.push(onrejected);
}
},
catch: function MyCatch() {}
}
if (typeof (Symbol) !== "undefined") Promise.prototype[Symbol.toStringTag] = 'Promise';
let P = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000);
})
P.then((res) => {
console.log(res)
})
进阶版Promise
const Promise = function Promise(executor) {
let self = this;
if (toType(executor) !== 'function') throw Error('Promise resolver ' + toType(executor) + ' is not a function');
if (!(self instanceof Promise)) throw new TypeError('undefined is not a promise');
self.state = 'pending';
self.value = undefined;
self.onfulfilledCallbacks = [];
self.onrejectedCabacks = [];
const change = function change(state, value) {
if (self.state !== 'pending') return;
self.state = state;
self.value = value;
setTimeout(() => {
var callbacks = self.state === 'fulfilled' ? self.onfulfilledCallbacks : self.onrejectedCabacks;
for (var i = 0; i < callbacks.length; i++) {
callbacks[i](self.value);
}
});
}
try {
executor(function (result) {
change('fulfilled', result);
}, function (reason) {
change('rejected', reason);
})
} catch (err) {
change('rejected', err.message);
}
return self
}
const handle = function handle(callback, value,resolve,reject) {
try {
let result = callback(value);
if (result instanceof Promise) {
result.then(resolve, reject);
return;
};
resolve(result);
} catch (err) {
reject(err.message)
}
}
Promise.prototype = {
constructor: Promise,
then: function then(onfulfilled, onrejected) {
let self = this;
return new Promise((resolve, reject) => {
switch (self.state) {
case 'fulfilled':
setTimeout(() => {
handle(onfulfilled,self.value,resolve, reject);
});
break;
case 'rejected':
setTimeout(() => {
handle(onrejected,self.value,resolve, reject);
});
break;
default:
self.onfulfilledCallbacks.push((value) => {
handle(onfulfilled,value,resolve, reject);
});
self.onrejectedCabacks.push((value) => {
handle(onrejected,self.value,resolve, reject);
});
}
})
},
catch: function MyCatch(onrejected) {
}
}
Promise.resolve = function resolve(result) {
return new Promise((resolve) => {
resolve(result);
})
}
Promise.catch = function MyCatch(reason) {
return new Promise((_, reject) => {
reject(reason);
})
}
Promise.all = function resolve() {
}
if (typeof (Symbol) !== "undefined") Promise.prototype[Symbol.toStringTag] = 'Promise';
const query = function query(time){
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(time);
}, time);
})
}
query(1000).then((result) => {
console.log(result);
return query(2000)
}).then((result) => {
console.log(result)
})
符合Promise A+规范
promisesaplus.com
~function () {
const Promise = function Promise(execute) {
let self = this;
self.state = 'pending';
self.value = undefined;
self.onfulfilledCallbacks = [];
self.onrejectedCallbacks = [];
const change = function change(state, value) {
if (self.state !== 'pending') return;
self.state = state;
self.value = value;
queueMicrotask(() => {
let Callbacks = self.state === 'fulfilled' ? self.onfulfilledCallbacks : self.onrejectedCallbacks;
Callbacks.forEach(v => {
v(self.value)
})
})
}
try {
execute(function onfulfilled(value) {
change('fulfilled', value)
}, function onrejected(value) {
change('rejected', value)
})
} catch (error) {
change('rejected', error)
}
}
const resolvePromise = function resolvePromise(promise, x, resolve, reject) {
if (promise === x) throw new TypeError('kk');
if (x!==null && /^(object|function)$/i.test(typeof x)) {
var then;
try {
then = x.then;
} catch (error) {
reject(error);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(x, function onresolve(y) {
if (called) return;
called = true;
resolvePromise(promise, y, resolve, reject)
}, function onreject(value) {
if (called) return;
called = true;
reject(value);
})
} catch (error) {
if (called) return;
reject(error);
}
return;
}
}
resolve(x);
}
const handle = function handle(callback, value, promise, resolve, reject) {
try {
let x = callback(value);
resolvePromise(promise, x, resolve, reject);
} catch (err) {
reject(err);
}
}
Promise.prototype = {
constructor: Promise,
then: function then(onfulfilled, onrejected) {
let promise = null,
self = this;
if (typeof onfulfilled !== 'function') {
onfulfilled = function onfulfilled(value) {
return value
}
}
if (typeof onrejected !== 'function') {
onrejected = function onrejected(value) {
throw value
}
}
promise = new Promise((resolve, reject) => {
switch (self.state) {
case "fulfilled":
queueMicrotask(() => {
handle(onfulfilled, self.value, promise, resolve, reject)
})
break;
case "rejected":
queueMicrotask(() => {
handle(onrejected, self.value, promise, resolve, reject)
})
break;
default:
self.onfulfilledCallbacks.push(function (value) {
handle(onfulfilled, value, promise, resolve, reject)
})
self.onrejectedCallbacks.push(function (value) {
handle(onrejected, value, promise, resolve, reject)
})
}
})
return promise
},
catch: function Mycatch(onrejected) {
this.then(null, onrejected);
}
}
Promise.prototype[Symbol.toStringTag] = 'Promise';
Promise.resolve = function resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
})
}
Promise.reject = function reject(value) {
return new Promise((resolve, reject) => {
reject(value);
})
}
Promise.all = function all(value) {
if (!Array.isArray(value)) throw new TypeError('value is not a Array');
let result = [];
return new Promise((resolve, reject) => {
value.forEach((v, i) => {
if (!isPromise(v)) v = Promise.resolve(v);
v.then((res) => {
result[i] = res;
if (result.length >= value.length) resolve(result);
}).catch((err) => {
reject(err);
})
})
})
}
Promise.race = function race(value) {
return new Promise((resolve, reject) => {
if (!Array.isArray(value)) throw new Error(`${value} is not function`);
value.forEach((v, i) => {
if (!(v instanceof Promise)) v = Promise.resolve(v);
v.then((res) => {
resolve(res);
}).catch((err) => {
reject(err);
})
})
})
}
Promise.deferred = function () {
var result = {};
result.promise = new Promise(function (resolve, reject) {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
if (typeof window !== 'undefined') window.Promise;
if (typeof module === 'object' && typeof module.exports === 'object') module.exports = Promise;
}()
调试办法
npm init -y
npm install promises-aplus-tests --save-dev
Promise.deferred = function () {
var result = {};
result.promise = new Promise(function (resolve, reject) {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
{
"scripts": {
"test": "promises-aplus-tests MyPromise.js"
},
......
}
npm run test