面试会遇到Promise,问你是怎么理解Promise的?git
个人理解就是承诺!es6
编码代码,存在异步的地方都会遇到Promise! 搞了这么久,感受理解不是很透github
突然想起一句话:学习法语糖的最好方法,是本身去实现ta,本身实现不了,就看比人怎么实现的面试
let promise = new Promise( function(resolve, reject) {
/* 异步操做 */ setTimeout(() => {
let number = Math.floor(Math.random() * 3)
if (number == 2) {
resolve(number);
} else {
reject('不是2')
}
}, 3000);
} )
promise.then(
(value) => {// then方法第一个参数onFulfilled,异步任务成功时调用
console.log(value);
},
(value) => {// then方法第二个参数onRejected,异步任务成功时调用
console.log(value);
}
);
复制代码
function Promise(fn) {
//校验
if (!(this instanceof Promise))
throw new TypeError('Promise 前面必须加new');
if (typeof fn !== 'function') throw new TypeError('not a function');
this._state = 0; // _state有三个值 0表明PENDING(进行中)
//1表明FULFILLED (已成功)
//2表明REJECTED(已失败)
//3表明传入resolve的是Promise实例
this._value = undefined; //异步任务完成获取的值 reslove()或者reject()中传递的值
this._deferreds = []; //存放then函数传递的回调
doResolve(fn, this);
}
复制代码
根据上面的例子能够看到Promise构造函数的参数是一个包含异步任务的函数数组
有了构造函数,接下来实现doResolve(fn, this),doResolve要作两件事,第一要执行咱们传入的promise
包含异步任务的函数,同时传入resolve,reject参数 function(resolve, reject) {,能够看上线的例子bash
function doResolve(fn, self) {
var done = false;
fn(
function(value) { //第一个参数resolve,当异步成功完成调用
if (done) return;
done = true;
resolve(self, value);
},
function(reason) { //第二个参数reject,当异步完成失败调用
if (done) return;
done = true;
reject(self, reason);
}
);
}
复制代码
其中利用闭包,保证传入的resolve,reject 只能调用一次,保持对self,Promise实例的引用闭包
接下来实现resolve,reject,方法只是记录下_state的状态dom
function resolve(self, newValue) {
self._state = 1;
self._value = newValue;
finale(self);
}
function reject(self, newValue) {
self._state = 2;
self._value = newValue;
finale(self);
}复制代码
实现finale,调用self._deferreds 存放then方法中传入的回调onFulfilled和onRejected异步
再没有调用then方法时,self._deferreds=[],当调用then 方法时判断self._state === 0是没有完成
就将then 方法的回调存入self._deferreds,若是已经完成,根据self._state为1或者2调用onFulfilled或者onRejected
function finale(self) {
for (var i = 0, len = self._deferreds.length; i < len; i++) {
handle(self, self._deferreds[i]);
}
self._deferreds = null;
}
function handle(self, deferred) {
if (self._state === 0) {
self._deferreds.push(deferred);
return;
}
setTimeout(function() {
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
cb(self._value);
}, 0);
}复制代码
实现then方法,当调用then 方法时判断self._state === 0是没有完成
就将then 方法的回调存入self._deferreds,若是已经完成,根据self._state为1或者2调用onFulfilled或者onRejected
Promise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
onRejected = typeof onRejected === 'function' ? onRejected : null;
handle(this, {onFulfilled,onRejected});
}复制代码
基本的Promise就实现了,去掉不少细节
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected);
};
Promise.resolve = function(value) {
if (value && typeof value === 'object' && value.constructor === Promise) {
return value;
}
return new Promise(function(resolve) {
resolve(value);
});
};
Promise.reject = function(value) {
return new Promise(function(resolve, reject) {
reject(value);
});
};
Promise.race = function(values) {
return new Promise(function(resolve, reject) {
for (var i = 0, len = values.length; i < len; i++) {
values[i].then(resolve, reject);
}
});
};
复制代码
这几个方法都很简单,复杂一点的是Promise.all;
Promise.all = function(arr) {
return new Promise(function(resolve, reject) {
if (!arr || typeof arr.length === 'undefined')
throw new TypeError('Promise.all accepts an array');
var args = Array.prototype.slice.call(arr);
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then;
if (typeof then === 'function') {
then.call(
val,
function(val) {
res(i, val);
},
reject
);
return;
}
}
args[i] = val;
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
复制代码
Promise.all传入的是一个Promise实例数组,经过计数方式当传入的Promise实例每完成一个--remaining,计数器减一,全部都完成了调用resolve触发then的回调
当你看完实现代码再结合阮一峰的讲解实例es6.ruanyifeng.com/#docs/promi…,应该能够更快的掌握
本文为了更好理解,省去了不少代码完整代码请查看promise-polyfill