赞
踩
Promise
标准仅描述了then
方法的行为,未对catch
、all
、race
方法进行描述,也未规范如何创建一个Promise
对象。ES6
中Promise
提供了以下API
。
(1) 构造函数
function Promise(resolver) {}
(2) 原型方法
- Promise.prototype.then = function() {}
- Promise.prototype.catch = function() {}
(3) 静态方法
- Promise.resolve = function() {}
- Promise.reject = function() {}
- Promise.all = function() {}
- Promise.race = function() {}
构造函数
1: Promise/A+
标准并没有指定如何构造一个Promise
对象,我们以ES6
原生Promise
模块里通过构造函数创建Promise
对象的方式实现Promise
构造函数。ES6
中通过构造函数创建Promise
对象的简单用法如下:
- const promise = new Promise((resolve) => {
- setTimeout(()=> {
- resolve(1);
- }, 2000);
- });
- promise.then(a=> alert(a));
- promise.then(a => alert(a+1));
构造函数用法总结:
(1) 构造函数接收一个executor
立即执行函数
(2) executor
立即执行函数接收一个resolve
函数
(3) promise
对象的then
方法绑定状态变为fulfilled
时的回调
(4) resolve
函数被调用时会触发then
方法中的回调
- function Promise(executor) {
- var self = this;
- self.status = 'pending'; //promise当前的状态
- self.data = undefined; //promise的值
- self.onResolvedCallback = [];
- //promise状态变为resolve时的回调函数集,可能有多个
- function resolve(value) {
- if(self.status === 'pending') {
- self.status = 'resolved';
- self.data = value;
- for(var i = 0; i < self.onResolvedCallback.length; i++) {
- self.onResolvedCallback[i](value);
- }
- }
- }
- executor(resolve);
- };
- Promise.prototype.then = function (resolve) {
- this.onResolvedCallback.push(resolve);
- };
3. executor
自执行函数接收的第二个参数为reject
函数且reject
函数在promise
对象状态变为rejected
时或executor
抛出异常时触发。
- function Promise(executor) {
- var self = this;
- self.status = 'pending'; //promise当前的状态
- self.data = undefined; //promise的值
- self.onResolvedCallback = [];
- //promise状态变为resolve时的回调函数集,可能有多个
- self.onRejectedCallback = [];
- //promise状态变为reject时的回调函数集,可能有多个
- function resolve(value) {
- if(self.status === 'pending') {
- self.status = 'resolved';
- self.data = value;
- for(var i = 0; i < self.onResolvedCallback.length; i++) {
- self.onResolvedCallback[i](value);
- }
- }
- }
-
- function reject(reason) {
- if(self.status === 'pending') {
- self.status = 'rejected';
- self.data = reason;
- for(var i = 0; i < self.onRejectedCallback.length; i++) {
- self.onRejectedCallback[i](reason);
- }
- }
- }
-
- try {
- executor(resolve, reject);
- } catch (e){
- reject(e);
- }
- };
- Promise.prototype.then = function (onResolve, onReject) {
- this.onResolvedCallback.push(onResolve);
- this.onRejectedCallback.push(onReject);
- };
then
方法并没有返回一个promise
对象,而 Promise/A+
规范中规定then
方法用来注册promise
对象状态改变时的回调,且返回一个新的promise
对象。then
方法返回一个新的promise
对象。executor
自执行函数中的resolve
参数调用时执行then
方法的第一个回调函数onResolved
。executor
自执行函数中的reject
参数调用时执行then
方法的第二个回调函数onRejected
。- Promise.prototype.then = function (onResolved, onRejected) {
- var self = this;
- var promise2;
- onResolved = typeof onResolved === 'function'
- ? onResolved
- : function (value) {return value};
- onRejected = typeof onRejected === 'function'
- ? onRejected
- : function (reason) {throw reason};
- //promise对象当前状态为resolved
- if(self.status === 'resolved') {
- return promise2 = new Promise(function (resolve, reject) {
- try {
- //调用onResolve回调函数
- var x = onResolved(self.data);
- //如果onResolve回调函数返回值为一个promise对象
- if(x instanceof Promise) {
- //将它的结果作为promise2的结果
- x.then(resolve, reject);
- } else {
- resolve(x);//执行promise2的onResolve回调
- }
- } catch (e) {
- reject(e); //执行promise2的onReject回调
- }
- })
- }
- //promise对象当前状态为rejected
- if(self.status === 'rejected') {
- return promise2 = new Promise(function (resolve, reject) {
- try {
- var x = onRejected(self.data);
- if (x instanceof Promise) {
- x.then(resolve, reject)
- } else {
- resolve(x)
- }
- } catch (e) {
- reject(e)
- }
- })
- }
- //promise对象当前状态为pending
- //此时并不能确定调用onResolved还是onRejected,需要等当前Promise状态确定。
- //所以需要将callBack放入promise1的回调数组中
- if(self.status === 'pending') {
- return promise2 = new Promise(function (resolve, reject) {
- self.onResolvedCallback.push(function (value) {
- try {
- var x = onResolved(self.data);
- if (x instanceof Promise) {
- x.then(resolve, reject);
- } else {
- resolve(x);
- }
- } catch (e) {
- reject(e);
- }
- })
- self.onRejectedCallback.push(function(reason) {
- try {
- var x = onRejected(self.data);
- if (x instanceof Promise) {
- x.then(resolve, reject)
- } else {
- resolve(x);
- }
- } catch (e) {
- reject(e)
- }
- })
- })
- }
- };
完整代码
- var Promise = (function() {
- function Promise(resolver) {
- if (typeof resolver !== 'function') { //resolver必须是函数
- throw new TypeError('Promise resolver ' + resolver + ' is not a function')
- }
- if (!(this instanceof Promise)) return new Promise(resolver)
-
- var self = this //保存this
- self.callbacks = [] //保存onResolve和onReject函数集合
- self.status = 'pending' //当前状态
-
- function resolve(value) {
- setTimeout(function() { //异步调用
- if (self.status !== 'pending') {
- return
- }
- self.status = 'resolved' //修改状态
- self.data = value
-
- for (var i = 0; i < self.callbacks.length; i++) {
- self.callbacks[i].onResolved(value)
- }
- })
- }
-
- function reject(reason) {
- setTimeout(function(){ //异步调用
- if (self.status !== 'pending') {
- return
- }
- self.status = 'rejected' //修改状态
- self.data = reason
-
- for (var i = 0; i < self.callbacks.length; i++) {
- self.callbacks[i].onRejected(reason)
- }
- })
- }
-
- try{
- resolver(resolve, reject) //执行resolver函数
- } catch(e) {
- reject(e)
- }
- }
-
- function resolvePromise(promise, x, resolve, reject) {
- var then
- var thenCalledOrThrow = false
-
- if (promise === x) {
- return reject(new TypeError('Chaining cycle detected for promise!'))
- }
-
- if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
- try {
- then = x.then
- if (typeof then === 'function') {
- then.call(x, function rs(y) {
- if (thenCalledOrThrow) return
- thenCalledOrThrow = true
- return resolvePromise(promise, y, resolve, reject)
- }, function rj(r) {
- if (thenCalledOrThrow) return
- thenCalledOrThrow = true
- return reject(r)
- })
- } else {
- return resolve(x)
- }
- } catch(e) {
- if (thenCalledOrThrow) return
- thenCalledOrThrow = true
- return reject(e)
- }
- } else {
- return resolve(x)
- }
- }
-
- Promise.prototype.then = function(onResolved, onRejected) {
- //健壮性处理,处理点击穿透
- onResolved = typeof onResolved === 'function' ? onResolved : function(v){return v}
- onRejected = typeof onRejected === 'function' ? onRejected : function(r){throw r}
- var self = this
- var promise2
-
- //promise状态为resolved
- if (self.status === 'resolved') {
- return promise2 = new Promise(function(resolve, reject) {
- setTimeout(function() {
- try {
- //调用then方法的onResolved回调
- var x = onResolved(self.data)
- //根据x的值修改promise2的状态
- resolvePromise(promise2, x, resolve, reject)
- } catch(e) {
- //promise2状态变为rejected
- return reject(e)
- }
- })
- })
- }
-
- //promise状态为rejected
- if (self.status === 'rejected') {
- return promise2 = new Promise(function(resolve, reject) {
- setTimeout(function() {
- try {
- //调用then方法的onReject回调
- var x = onRejected(self.data)
- //根据x的值修改promise2的状态
- resolvePromise(promise2, x, resolve, reject)
- } catch(e) {
- //promise2状态变为rejected
- return reject(e)
- }
- })
- })
- }
-
- //promise状态为pending
- //需要等待promise的状态改变
- if (self.status === 'pending') {
- return promise2 = new Promise(function(resolve, reject) {
- self.callbacks.push({
- onResolved: function(value) {
- try {
- //调用then方法的onResolved回调
- var x = onResolved(value)
- //根据x的值修改promise2的状态
- resolvePromise(promise2, x, resolve, reject)
- } catch(e) {
- //promise2状态变为rejected
- return reject(e)
- }
- },
- onRejected: function(reason) {
- try {
- //调用then方法的onResolved回调
- var x = onRejected(reason)
- //根据x的值修改promise2的状态
- resolvePromise(promise2, x, resolve, reject)
- } catch(e) {
- //promise2状态变为rejected
- return reject(e)
- }
- }
- })
- })
- }
- }
-
- //获取当前Promise传递的值
- Promise.prototype.valueOf = function() {
- return this.data
- }
-
- //由then方法实现catch方法
- Promise.prototype.catch = function(onRejected) {
- return this.then(null, onRejected)
- }
-
- //finally方法
- Promise.prototype.finally = function(fn) {
- return this.then(function(v){
- setTimeout(fn)
- return v
- }, function(r){
- setTimeout(fn)
- throw r
- })
- }
-
- Promise.prototype.spread = function(fn, onRejected) {
- return this.then(function(values) {
- return fn.apply(null, values)
- }, onRejected)
- }
-
- Promise.prototype.inject = function(fn, onRejected) {
- return this.then(function(v) {
- return fn.apply(null, fn.toString().match(/\((.*?)\)/)[1].split(',').map(function(key){
- return v[key];
- }))
- }, onRejected)
- }
-
- Promise.prototype.delay = function(duration) {
- return this.then(function(value) {
- return new Promise(function(resolve, reject) {
- setTimeout(function() {
- resolve(value)
- }, duration)
- })
- }, function(reason) {
- return new Promise(function(resolve, reject) {
- setTimeout(function() {
- reject(reason)
- }, duration)
- })
- })
- }
-
- Promise.all = function(promises) {
- return new Promise(function(resolve, reject) {
- var resolvedCounter = 0
- var promiseNum = promises.length
- var resolvedValues = new Array(promiseNum)
- for (var i = 0; i < promiseNum; i++) {
- (function(i) {
- Promise.resolve(promises[i]).then(function(value) {
- resolvedCounter++
- resolvedValues[i] = value
- if (resolvedCounter == promiseNum) {
- return resolve(resolvedValues)
- }
- }, function(reason) {
- return reject(reason)
- })
- })(i)
- }
- })
- }
-
- Promise.race = function(promises) {
- return new Promise(function(resolve, reject) {
- for (var i = 0; i < promises.length; i++) {
- Promise.resolve(promises[i]).then(function(value) {
- return resolve(value)
- }, function(reason) {
- return reject(reason)
- })
- }
- })
- }
-
- Promise.resolve = function(value) {
- var promise = new Promise(function(resolve, reject) {
- resolvePromise(promise, value, resolve, reject)
- })
- return promise
- }
-
- Promise.reject = function(reason) {
- return new Promise(function(resolve, reject) {
- reject(reason)
- })
- }
-
- Promise.fcall = function(fn){
- // 虽然fn可以接收到上一层then里传来的参数,但是其实是undefined,所以跟没有是一样的,因为resolve没参数啊
- return Promise.resolve().then(fn)
- }
-
- Promise.done = Promise.stop = function(){
- return new Promise(function(){})
- }
-
- Promise.deferred = Promise.defer = function() {
- var dfd = {}
- dfd.promise = new Promise(function(resolve, reject) {
- dfd.resolve = resolve
- dfd.reject = reject
- })
- return dfd
- }
-
- try { // CommonJS compliance
- module.exports = Promise
- } catch(e) {}
-
- return Promise
- })()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。