Promise初始结构搭建
let p = new Promise((resolve,reject)=>{
resolve('OK')
})
p.then(value=>{
console.log(value);
},reason=>{
console.warn(reason);
})
- 参考原始Promise对象中的结构,构造函数
Promise 中包含一个执行器函数,原型上有then 方法,该方法接收两个函数参数 - 搭建好结构:
function myPromise(executor){
}
myPromise.prototype.then = function(onResolved,onRejected){
}
resolve与reject结构搭建
- 考虑到
Promise对象 中的执行器函数是同步调用的,并且具有两个函数参数(resolve, reject) ,需要对这两个函数在构造函数内部进行声明,考虑到原始构造中函数有传递参数值data
function myPromise(executor){
function resolve(data){
}
function reject(data){
}
executor(resolve, reject)
}
resolve与reject代码实现
- promise状态会发生改变
- 设置成功的结果
- 为了给实例对象表示状态的转变以及数据的传输,需要设定两个值
function myPromise(executor){
this.promiseState = 'pendinng'
this.promiseResult = null
function resolve(data){
this.promiseState = 'fulfilled'
this.promiseResult = data
}
- 若直接如上方式书写,this的指向会指向window而非实例对象
- 因此需要保存实例对象的this值
function myPromise(executor){
this.promiseState = 'pendinng'
this.promiseResult = null
const self = this
function resolve(data){
self.promiseState = 'fulfilled'
self.promiseResult = data
}
}
function reject(data){
self.promiseState = 'rejected'
self.promiseResult = data
}
throw抛出异常改变状态
let p = new Promise((resolve,reject)=>{
throw "error"
})
console.log(p)
- 如何处理
throw ?想到try..catch.. 方法 - 往哪里加
try..catch.. ?考虑到是在执行器函数内部执行,通过catch 捕捉的throw 后,调用reject 函数修改状态
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
Promise对象状态只能修改一次
- 由于状态只能改变一次,且只能由
pendding 状态变为其他,故要进行判断
function resolve(data) {
if (self.promiseState !== 'pendinng') return;
self.promiseState = 'fulfilled'
self.promiseResult = data
}
function reject(data) {
if (self.promiseState !== 'pendinng') return;
self.promiseState = 'rejected'
self.promiseResult = data
}
then方法执行回调
myPromise.prototype.then = function (onResolved, onRejected) {
if (this.promiseState === 'fulfilled'){
onResolved(this.promiseResult)
}
if (this.promiseState === 'rejected') {
onRejected(this.promiseResult)
}
}
异步任务then回调的执行
- 若异步执行回调函数,then方法不会执行,由于异步,状态还未发生改变,便执行then方法
let p = new myPromise((resolve,reject)=>{
setTimeout(() => {
resolve('OK')
}, 1000);
})
- 故还需要进行判断,真正调用回调函数的时机是在
(resolve, reject) 中,我们需要在then方法中保存回调函数,在Promise 对象中声明一个属性保存成功和失败的回调函数
function myPromise(executor) {
this.promiseState = 'pendinng'
this.promiseResult = null
this.callback = {}
- 在then方法中判断,一旦promise 是pendding状态,将回调函数保存到该属性中
myPromise.prototype.then = function (onResolved, onRejected) {
if (this.promiseState === 'fulfilled'){
onResolved(this.promiseResult)
}
if (this.promiseState === 'rejected') {
onRejected(this.promiseResult)
}
if (this.promiseState === 'pendinng'){
this.callback = {
onResolved,
onRejected
}
}
}
- 然后在promise对象中对应的
(resolve, reject) 函数里面调用
function resolve(data) {
if (self.promiseState !== 'pendinng') return;
self.promiseState = 'fulfilled'
self.promiseResult = data
if(self.callback.onResolved){
self.callback.onResolved(data)
}
}
指定多个回调的实现
- 上述方法修改回调函数会存在一个问题,若是后面新增的then方法会将之前的回调函数覆盖
p.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
p.then(value => {
alert(value);
}, reason => {
alert(reason);
})
- 更改:用数组保存回调函数,在
(resolve, reject) 函数遍历执行
this.callbacks = []
------------.then-----------
if (this.promiseState === 'pendinng'){
this.callbacks.push({
onResolved,
onRejected
})
}
-----------(resolve, reject)------------
self.callbacks.forEach(item=>{
item.onResolved(data)
})
同步任务下修改状态then方法结果返回
- 由于then方法的返回值是一个promise对象,由参数函数的状态及值决定
const result = p.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
console.log(result);
- 首先then方法实现的是一个promise对象,然后考虑到回调函数返回的是promise对象还是值还是抛出错误
myPromise.prototype.then = function (onResolved, onRejected) {
return new myPromise((resolve,reject)=>{
if (this.promiseState === 'fulfilled') {
try {
let result = onResolved(this.promiseResult)
if (result instanceof myPromise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
...reject
}
异步任务下修改状态then方法结果返回
- 若是异步,由于状态仍然是pendding,进入到此时的then方法中,并没有调用resolve或者reject函数,因此返回的结果promise仍然是pendding状态
const self = this
if (this.promiseState === 'pendinng') {
this.callbacks.push({
onResolved: function () {
try {
let result = onResolved(this.promiseResult)
if (result instanceof myPromise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
},
onRejected: function () {
}
then方法的完善和优化
function callback(type) {
try {
let result = type(self.promiseResult)
if (result instanceof myPromise) {
result.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
-------------then return ---------------
if (this.promiseState === 'fulfilled') {
callback(onResolved)
}
if (this.promiseState === 'rejected') {
callback(onRejected)
}
then方法回调的异步执行
let p = new myPromise((resolve, reject) => {
resolve('OK')
console.log(111);
})
p.then(value => {
console.log(222);
})
console.log(333);
- 需要在then方法成功和失败的状态下,以及promise对象中的resolve和reject的回调函数数组,用定时器包裹
-----------------.then ------------------
if (this.promiseState === 'fulfilled') {
setTimeout(() => {
callback(onResolved)
});
}
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data)
})
});
catch方法-异常穿透与值传递
p.catch(reason=>{
console.warn(reason);
})
myPromise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected)
}
- 实现异常穿透和值传递,让then方法中的两个函数参数是可传可不传的
if(typeof onResolved!== 'function'){
onResolved= value => value
}
if(typeof onRejected !== 'function'){
onRejected = reason=>{
throw reason
}
}
promise函数上resolve方法的封装
const p = Promise.resolve('OK')
myPromise.resolve = function(value){
return new myPromise((resolve,reject)=>{
if (value instanceof myPromise) {
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
promise函数上reject方法的封装
myPromise.resolve = function (reason) {
return new myPromise((resolve, reject) => {
reject(reason)
})
}
promise函数上all方法的封装
- 返回promise对象,参数为promise组成的数组,结果为成功结果的数组,有一个失败就失败
myPromise.all = function (promises) {
return new myPromise((resolve, reject) => {
let count = 0
let res = []
for(let i = 0;i < promises.length;i++){
promises[i].then(v=>{
count++
res[i] = v
if(count === promises.length) resolve(res);
},r=>{
reject(r)
})
}
})
}
promise函数上race方法的封装
myPromise.race = function (promises) {
return new myPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v);
}, r => {
reject(r)
})
}
})
}
class版本实现
class Promise {
constructor(executor) {
this.PromiseState = 'pending';
this.PromiseResult = null;
this.callbacks = [];
let resolve = (data) => {
if (this.PromiseState !== 'pending') return;
this.PromiseState = 'fulfilled';
this.PromiseResult = data;
setTimeout(() => {
this.callbacks.forEach(item => {
item.onResolved(data);
});
});
}
let reject = (data) => {
if (this.PromiseState !== 'pending') return;
this.PromiseState = 'rejected';
this.PromiseResult = data;
setTimeout(() => {
this.callbacks.forEach(item => {
item.onRejected(data);
});
});
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onResolved, onRejected) {
if (typeof onRejected !== 'function') {
onRejected = reason => {
throw reason;
}
}
if (typeof onResolved !== 'function') {
onResolved = value => value;
}
return new Promise((resolve, reject) => {
let callback = (type) => {
try {
let result = type(this.PromiseResult);
if (result instanceof Promise) {
result.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
resolve(result);
}
} catch (e) {
reject(e);
}
}
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
callback(onResolved);
});
}
if (this.PromiseState === 'rejected') {
setTimeout(() => {
callback(onRejected);
});
}
if (this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: function () {
callback(onResolved);
},
onRejected: function () {
callback(onRejected);
}
});
}
})
}
catch (onRejected) {
return this.then(undefined, onRejected);
}
static resolve(value) {
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
value.then(v => {
resolve(v);
}, r => {
reject(r);
})
} else {
resolve(value);
}
});
}
static reject(reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
}
static all(promises) {
return new Promise((resolve, reject) => {
let count = 0;
let arr = [];
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
count++;
arr[i] = v;
if (count === promises.length) {
resolve(arr);
}
}, r => {
reject(r);
});
}
});
}
static race(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(v => {
resolve(v);
}, r => {
reject(r);
})
}
});
}
}
|