假如让你完成一个 promise ,你会怎么做?
本身完成promise的大致思绪
- 我们要明白我们须要一个异步的操纵要领,满足异步回调。所以挑选到场setTimeout 作为完成的基本, 让函数完成耽误触发。
- 坚持一个准绳,掌握 promise 转变状况的只要 promise 组织函数里的 reslove 、 reject 函数。
- 链式挪用的道理, 相似jQuery,它会在挪用要领后, return this. 从而构成链式挪用。所以我们采用在挪用then(fn)、 catch(fn) 后 会返回一个新的 promise 对象, 但是 这个 promise 对象 遭到 它的上级promise 对象的状况效果 和 fn 运转效果的掌握。
学问点:
内里 应当 用到点 js 作用域 、 函数闭包、 继续 、 上下文 绑定学问、援用通报。
存在题目
cbList、rhList、 cs 这个三个, Promise 对象能直接接见, 假如对其直接操纵能够形成 顺序杂乱。
代码若有马虎,望人人斧正
var JcPromise = function (fn) {
// 防备 用户 直接 变动 state
var state = 'wait'
// state 为 resolve 状况, 回调函数数组
var cbList = []
// state 为 reject 状况, 回调函数数组
var rjList = []
this.cbList = cbList
this.rjList = rjList
//
this.cs = undefined
// 猎取 promise 的状况
this.getState = function () {
return state
}
/* 函数闭包,函数 定义在内里, 防备 表面用户 直接 运用 resolve 和 reject; */
// Promise胜利触发 函数
var reslove = function (data) {
this.cs = data
if (state !== 'wait') {
return
} else {
state = 'solve'
while (this.cbList.length) {
cbList.shift()(data)
}
}
}
// Promise 谢绝 触发函数
var reject = function (e) {
this.cs = e
if (state !== 'wait') {
return
} else {
state = 'reject'
while (rjList.length) {
rjList.shift()(e)
}
}
}
// 绑定函数 conext 及 this 为当前 promise对象
reslove = reslove.bind(this)
reject = reject.bind(this)
// 耽误 触发
setTimeout(function () {
fn(reslove, reject)
}, 0)
}
JcPromise.prototype.then = function (fn) {
var handleObj = {}
var nextPromise = new JcPromise(function (r, j) {
handleObj.r = r
handleObj.j = j
})
var fixFn = function (data) {
var result = null
try {
result = fn(data)
// 推断result是否是 JcPromise实例。
if (result instanceof JcPromise) {
result.then(function (data) {
handleObj.r(data)
}).catch(function (e) {
handleObj.j(e)
})
} else {
handleObj.r(result)
}
} catch (e){
handleObj.j(e)
}
}
//推断当前状况 假如 是 solve 直接 运转, 假如不是,酒吧 fixFn 推入 cbList 数组。
if (this.getState() === 'solve') {
setTimeout(function () {
fixFn(this.cs)
}, 0)
} else {
this.cbList.push(fixFn)
}
return nextPromise
}
JcPromise.prototype.catch = function (fn) {
var handleObj = {}
var nextPromise = new JcPromise(function (r, j) {
handleObj.r = r
handleObj.j = j
})
var fixFn = function (e) {
var result = null
try {
result = fn(e)
if (result instanceof JcPromise) {
result.then(function (data) {
handleObj.r(data)
}).catch(function (e) {
handleObj.j(e)
})
} else {
handleObj.r(result)
}
} catch (e){
handleObj.j(e)
}
}
if (this.getState() === "reject") {
setTimeout(function () {
fixFn(this.cs)
}, 0)
} else {
this.rjList.push(fixFn)
}
return nextPromise
}
// 测试代码
var p = new JcPromise(function(r, j) {
setTimeout(function() {r(100)}, 3000)
}).then(data => {
console.log('1', data)
return new JcPromise((r, j) => {
setTimeout(() => {
r('hi')
}, 3000)
})
}).then(data => console.log('2', data)).then(function () {
console.log('xxx', xx + 1)
}).catch(e => console.log(e)).then(data => console.log(data, 'end'))
demo 测试
第二版 jcPromise 完成
var JcPromise = (function() {
function JcPromise(fn) {
fn = fn || noop;
var statusList = ['start', 'pending', 'succeed', 'err'];
var cbStatus = [0, 1];
var status = statusList[0];
var data = null;
var err = null;
var that = this;
var successFn = [];
var errFn = [];
function resolve(d) {
data = d;
that._changeStatus(2);
};
function reject(e) {
err = e;
that._changeStatus(3);
};
this.getData = function() {
return data;
};
this.getErr = function() {
return err
};
this.getStatus = function() {
return status
};
this._changeStatus = function(idx) {
switch (status) {
case statusList[2]:
case statusList[3]:
{
return false
}
};
status = statusList[idx];
if (status === statusList[3]) {
setTimeout(function() {
that._triggerCatch();
}, 0)
}
if (status === statusList[2]) {
setTimeout(function() {
that._triggerThen();
}, 0)
}
};
this._pushThenCb = function(cb) {
successFn.push({
status: cbStatus[0],
cb: cb
});
if (status === statusList[2]) {
this._triggerThen();
}
};
this._pushCatchCb = function(cb) {
errFn.push({
status: cbStatus[0],
cb: cb
});
if (status === statusList[3]) {
this._triggerCatch();
}
};
this._triggerThen = function() {
successFn.map(function(item) {
if (item.status === cbStatus[0]) {
item.cb(data);
item.status = cbStatus[1];
}
})
};
this._triggerCatch = function() {
errFn.map(function(item) {
if (item.status === cbStatus[0]) {
item.cb(err);
item.status = cbStatus[1];
}
})
};
this._changeStatus(1);
this.uuid = uuid++;
try {
fn(resolve, reject);
} catch (e) {
reject(e)
}
return this
};
JcPromise.fn = JcPromise.prototype;
// 返回一个promise
JcPromise.fn.then = function(cb) {
var promiseR = null;
var promiseJ = null;
var result = null;
var that = this;
var fn = function() {
setTimeout(function() {
try {
var data = that.getData();
result = cb(data);
if (typeof result === 'object' && result !== null && result.constructor === JcPromise) {
result.then(function(data) {
promiseR(data)
}).catch(function(e) {
promiseJ(e)
})
} else {
promiseR(result)
}
} catch (e) {
promiseJ(e)
}
}, 0);
};
this._pushThenCb(fn);
// 触发promise
return new JcPromise(function(r, j) {
promiseR = r;
promiseJ = j;
});
};
// 返回一个promise
JcPromise.fn.catch = function(cb) {
var promiseR = null;
var promiseJ = null;
var result = null;
var that = this;
var fn = function() {
setTimeout(function() {
try {
var data = that.getErr();
result = cb(data);
if (typeof result === 'object' && result !== null && result.constructor === JcPromise) {
result.then(function(data) {
promiseR(data)
}).catch(function(e) {
promiseJ(e)
})
} else {
promiseR(result)
}
} catch (e) {
promiseJ(e)
}
}, 0)
};
this._pushCatchCb(fn);
// 触发promise
return new JcPromise(function(r, j) {
promiseR = r;
promiseJ = j;
});
};
return JcPromise
})();