支持Promise.all,Promise.resolve,Promise.defer,finally,其他的功能没有做,有兴趣的可以自己尝试补充
Promise.js
var PENDING = 'PENDING';
var RESOLVE = 'RESOLVE';
var REJECT = 'REJECT';
var isPromise = function (arg) {
if (typeof arg === 'object' && arg !== null || typeof arg === 'function') {
if (typeof arg.then === 'function') {
return true;
} else {
return false;
}
} else {
return false;
}
}
var resolvePromise = function (promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
if (typeof x === 'object' && x !== null || typeof x === 'function') {
var called;
try {
var then = x.then;
if (typeof then === 'function') {
then.call(x, function (y) {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, function (r) {
if (called) return;
called = true;
reject(r);
})
} else {
if (called) return;
called = true;
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
function Promise(execute) {
var _self = this;
this.status = PENDING;
this.onFulfilledCbs = [];
this.onRejectedCbs = [];
this.resolve = function (value) {
if (_self.status === PENDING) {
_self.status = RESOLVE;
_self.value = value;
_self.onFulfilledCbs.forEach(function (item) {
return item();
});
}
}
this.reject = function (value) {
if (_self.status === PENDING) {
_self.status = REJECT;
_self.value = value;
_self.onRejectedCbs.forEach(function (item) {
return item();
});
}
}
try {
execute(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
Promise.prototype.then = function (onFulfilled, onRejected) {
var _self = this;
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) { return data };
onRejected = typeof onRejected === 'function' ? onRejected : function (err) { throw err };
var promise2 = new Promise(function (resolve, reject) {
if (_self.status === RESOLVE) {
setTimeout(function () {
try {
var x = onFulfilled(_self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (_self.status === REJECT) {
setTimeout(function () {
try {
var x = onRejected(_self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (_self.status === PENDING) {
_self.onFulfilledCbs.push(function () {
setTimeout(function () {
try {
var x = onFulfilled(_self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
})
_self.onRejectedCbs.push(function () {
setTimeout(function () {
try {
var x = onRejected(_self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
})
}
})
return promise2;
}
Promise.prototype.finally = function (cb) {
return this.then(function (data) {
return Promise.resolve(cb()).then(function () {
return data;
})
}, function (err) {
return Promise.resolve(cb()).then(function () {
throw err;
})
})
}
Promise.resolve = function (arg) {
if (isPromise(arg)) {
var promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
var x = arg.then();
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
})
return promise2;
} else {
return new Promise(function (resolve, reject) {
resolve(arg);
})
}
}
Promise.defer = Promise.deferred = function () {
var dfd = {};
dfd.promise = new Promise(function (resolve, reject) {
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
Promise.all = function(values) {
return new Promise(function (resolve, reject) {
var arr = [];
var index = 0;
var pushIn = function (key, data) {
arr[key] = data;
index++;
if (index === values.length) resolve(arr);
}
for (var i = 0; i < values.length; i++) {
(function (i) {
var item = values[i];
if (isPromise(item)) {
item.then(function(data){
pushIn(i, data);
}, reject);
} else {
pushIn(i, item);
}
})(i)
}
})
}
例子
new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("then1");
}, 2000);
})
.then(function(data) {
console.log(data);
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("then2");
}, 2000);
});
})
.then(function(data) {
console.log(data);
})
.finally(function() {
console.log("finally");
});
Promise.resolve(
new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("then1");
}, 2000);
}).then(function(data) {
console.log(data);
})
).then(function(data) {
console.log("abc");
});
Promise.all([
new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("then1");
}, 2000);
}),
new Promise(function(resolve, reject) {
setTimeout(function() {
resolve("then1");
}, 2000);
})
]).then(function(param) {
console.log(param);
});
自己实现promise的基础功能(es6)
class Promise {
callbacks = [];
constructor(fn) {debugger
fn(this._resolve.bind(this));
}
then(onFulfilled) {
this.callbacks.push(onFulfilled);
return this;//看这里
}
_resolve(value) {
this.callbacks.forEach(fn => fn(value));
}
}
var p = new Promise(resolve => {
setTimeout(() => {
console.log('done');
resolve('5秒');
}, 5000);
}).then(tip => {
console.log('then1', tip);
}).then(tip => {
console.log('then2', tip);
});