最先前
Promise
的完成道理已在 Promise 范例解读及完成细节 (一) 中说的很清晰了,这里将详细剖析 Promises/A+范例 中的Promise
剖析历程,最后会完成一个 Promise
并供应用于测试的代码
then 要领剖析
promise.then(fn1).then(fn2).then(fn3)
这里 promise.then()
的挪用会发生一个新的promise(差别实例)
关于 then(fn)
上一级 promise
的终值会作为 fn
的参数被传入
关于 then(fn)
假如 then
返回一个 promise1
,fn
返回一个 promise2
那末 promise1
的状况和值由 promise2
决议
关于 then(fn)
假如 then
返回一个 promise1
,fn
返回一个 promise2
我们想依赖于promise2
的挪用会被增加到 promise1
中
怎样让 promise2
决议 promise1
的结果
假如promise2
有 then
方 var promise2Then = promise2.then
,我们如许promise2Then.bind(promise1,resolve,reject)
promise
的状况和终值都是经由过程 当前 promise
的 resolve
和 reject
来转变的,所以只须要将 promise1
的这两个函数经由过程promise2
的 then
要领增加的 promise2
的实行行列中就能够到达想要的结果
Promise 剖析历程
关于 promise.then(fn)
,then
要领返回 promise1
,fn
要领返回 x
,fn
接收到的参数为 y
,这时候须要对 x
和 y
离别运转Promise
剖析历程
x: [[Resolve]](promise1, x)
y: [[Resolve]](promise1, y)
x
的剖析历程处置惩罚的是 回掉中返回 promise
的状况y
的剖析历程处置惩罚的是 向当前 promise
通报处置惩罚结果的谁人 promise
的终值是 promise
的状况
因而可知 promise
的剖析历程是递归的,递归的尽头是 x
,y
不是promise
,在是对象或许函数的情况下不具有 then
要领
代码组织
(function(window) {
var PENDING = 0; //PENDING 状况
var RESOLVED = 1; //RESOLVED 状况
var REJECTED = 2; //REJECTED 状况
function IPromise(fn) {
if (!(this instanceof IPromise)) return new IPromise(fn); //确保 经由过程 new IPromise() 和 IPromise() 都能准确建立对象
var state = PENDING; //promise 状况
var value = null; //终值
var callback = []; //回掉函数行列,在一种是两个行列,这里是一个,所以寄存的是对象
function reject(reason) {} //reject 要领
function resolve(result) {} //和(一)中的对照 这里多了 实行 Promise 剖析历程 的功用
function handle(handler) {} //增加或实行队 callback 中的挪用
/**
*@param onFulfilled 经由过程 then 要领增加的 onFulfilled
*@param onRejected 经由过程 then 要领增加的 onRejected
*
*@func 包装用户增加的回调
*因为这里只要一个回掉行列所以须要用 candy(糖果) 包装成{onFulfilled:onFulfilled,onRejected:onRejected}
*
*@func 耽误挪用handle
*在 Promise 范例解读及完成细节 (一) 中说 Promise(浏览器完成) 会被加入到microtask,因为浏览器没有供应除Promise
*以外microtask的接口,所以 我们要用 setTimeout 来耽误挪用并增加到 macrotask
*
*/
function candy(onFulfilled, onRejected) {}
function getThen(value) {} //推断 value 是不是有 then 要领假如有则猎取
this.then = function(onFulfilled, onRejected) {} //暴露的 then 要领
doResolve(fn, resolve, reject); //实行 fn
window.IPromise = IPromise; //将 IPromise 增加到浏览器的 window 上
}
/**
*Promise 剖析历程
*/
function doResolve(fn, resolvePromise, rejectPromise) {} //静态私有要领,剖析并实行promise(剖析并实行fn和promise的处置惩罚结果)
})(window);
以上经由过程 js
自实行函数将变量和函数限定在了作用域中,在全局的 window
上只暴露一个组织函数 IPromise
保证了全局不被污染
详细代码及诠释(请在浏览器中运转)
/**
*@author ivenj
*@date 2016-12-06
*@version 1.0
*/
(function(window) {
var PENDING = 0;
var RESOLVED = 1;
var REJECTED = 2;
function IPromise(fn) {
if (!(this instanceof IPromise)) return new IPromise(fn);
var state = PENDING;
var value = null;
var callback = [];
function reject(reason) {
state = REJECTED;
value = reason;
callback.forEach(handle);
callback = null;
}
/**
* 这里新增的内容是 满足Promise剖析历程时 resolve和doResolve互相挪用构成递归
**/
function resolve(result) {
try {
var then = getThen(result);
if (then) {
doResolve(then.bind(result), resolve, reject); //aa
return; //这里假如 resule 是有 then 要领则实行 doResolve 并返回不实行后续代码
}
//只要 result 不满足 剖析历程时实行,即递归尽头
state = RESOLVED;
value = result;
callback.forEach(handle);
callback = null;
} catch (e) {
reject(e);
}
}
function handle(handler) {
if (state === PENDING) {
callback.push(handler);
} else {
if (state === RESOLVED && typeof handler.onFulfilled === 'function') {
handler.onFulfilled(value);
}
if (state === REJECTED && typeof handler.onRejected === 'function') {
handler.onRejected(value);
}
}
}
function candy(onFulfilled, onRejected) {
setTimeout(function() {
handle({
onFulfilled: onFulfilled,
onRejected: onRejected
});
}, 0);
}
function getThen(value) {
var type = typeof value;
if (value && (type === 'object' || type === 'function')) {
try{
var then = value.then;
}catch(e){
reject(e);
}
if (typeof then === 'function') {
return then;
}
}
return null;
}
this.then = function(onFulfilled, onRejected) {
var self = this;
return new IPromise(function(resolve, reject) {
candy(function(x) {
if (typeof onFulfilled === 'function') {
try {
resolve(onFulfilled(x)); //cc 运转 [[Resolve]](promise, x)
} catch (e) {
reject(e);
}
} else {
resolve(x);
}
}, function(error) {
if (typeof onRejected === 'function') {
try {
resolve(onRejected(error));
} catch (e) {
reject(e);
}
} else {
reject(error);
}
});
});
};
doResolve(fn, resolve, reject);
}
/**
*Promise 剖析历程
*/
function doResolve(fn, resolvePromise, rejectPromise) {
var done = false; //用于保证只挪用一次
try {
fn(function(y) {
if (done) return;
done = true;
resolvePromise(y); //bb 假如 resolvePromise 以值 y 为参数被挪用,则运转 [[Resolve]](promise, y)
}, function(reason) {
if (done) return;
done = true;
rejectPromise(reason);
});
} catch (e) {
if (done) return;
done = true;
rejectPromise(e);
}
}
window.IPromise = IPromise;
})(window);
这里是用于测试的代码 读者将以上代码和以下代码粘贴到浏览器去运转 一秒后会打印 {url: "http://ivenj_", value: 10}
function post(url, callback) {
setTimeout(function() {
var data = { //模仿异步处置惩罚结果
url:url,
value:10
};
callback(data);
}, 1000);
}
var promise = IPromise(function(resolve, reject){
post('http://ivenj_', function(data){
resolve(data);
});
});
promise.then(function(data){
console.log(data);
});
Promise
完成最中心的内容是代码中的 //aa
//bb
//cc
读者须要偏重体味这三处
Promise 到此已完毕