https://cloud.tencent.com/developer/article/1361997
promise的then做了什么
学习: https://segmentfault.com/a/1190000010420744?utm_source=tag-newest
- then接受两个参数 promise.then(onFullfilled, onRejected),会返回一个promise对象,这也是链式调用的原理
- 对传入的两个回调函数进行处理
1、如果为值 则直接resolve该值
2、如果为普通函数,则执行该函数,函数的返回值作为普通值则resolve该值,没有返回值则resolve上次的值(透传)
3、如果返回值为promise函数,则执行该函数,并取当前返回的promise函数作为resolve值进行透传(也就是这次的状态跟返回的promise对象状态保持一致) - 根据当前状态不同处理回调
1、pending态,返回promise,并将两个回调函数分别压栈
2、fullfilled或rejected态,返回promise,并执行对应的(onFullfilled(thia.value), onRejected(this.reason))函数
let func = function() {
return new Promise((resolve, reject) => {
resolve('返回值');
});
};
let cb = function() {
return '新的值';
}
// 是函数 则将函数的返回值cb() 执行了 的值返回给下一个then
func().then(function () {
return cb();
}).then(resp => {
console.warn(resp); // 新的值
console.warn('1 =========<');
});
// 执行了 但是没有返回值
func().then(function () {
cb();
}).then(resp => {
console.warn(resp); // undefined
console.warn('2 =========<');
});
// 是一个值 被忽略 返回了上一个then resolve的值
func().then(cb()).then(resp => {
console.warn(resp); // 返回值
console.warn('3 =========<');
});
// 是一个函数且有返回值
func().then(cb).then(resp => {
console.warn(resp); // 新的值
console.warn('4 =========<');
});
promise.then接受一个promise对象
Promise.resolve('foo')
//第一个promise已经resolve,将'foo'传入第一个then。
.then(function(string) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
string += 'bar';
resolve(string);
}, 1000);//将1ms改为1s更易观察
});
})
// @1
.then(function(string) {
setTimeout(function() {
string += 'baz';
console.log(string);
}, 1000)
return string;
})
//@2
.then(function(string) {
console.log("Last Then: oops... didn't bother to instantiate and return " +
"a promise in the prior then so the sequence may be a bit " +
"surprising");
console.log(string);
});
//由于第二个then中return的string值为'foobar',因此先输出'foobar'。
// 并在前面的1s定时结束后执行string += 'baz', 最后输出foobarbaz。
- 第一个then中的函数返回一个promise对象,该promise对象状态为pending,根据‘如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。 ’摘自MDN。直到setTimeout时间到达,调用resolve(string),状态变为fulfilled(resolve),才调用下一个then方法。
- 在第二个then中,先调用setTimeout(setTimeout调用定时器后不会等待计时完成,而是继续执行下面的代码, 在1s的定时结束后再将其中的程序加入任务队列),然后跳到return string,由于setTimeout内代码尚未执行,此时string == 'foobar'。且根据 ‘如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态, 并且将返回的值作为接受状态的回调函数的参数值。’摘自MDN。 因此进入下一个then,且该段代码没有任何延时。
实现一个promise
class simplePromise {
constructor(exec) {
this.status = 'pending'
this.value = undefined
this.reason = undefined
this.fullfillCalls = []
this.rejectCalls = []
let that = this
function resolve(value) {
// 状态只能从pending到 fullfilled 或者pending到rejected
if (that.status !== 'pending') return
// 真正的promise可能是通过其他延迟实现,
// 我的理解是这里resolve并不会直接结束而是要去执行一些其他的同步语句
// 如果有异步的话 可能要等待所有异步的完成?
setTimeout(() => {
that.status = 'fullfilled'
that.value = value
// then是可以连续回调的
that.fullfillCalls.forEach(fn => fn && fn(value))
})
}
function reject(error) {
if (that.status !== 'pending') return
setTimeout(() => {
that.status = 'rejected'
that.rejectCalls.forEach(fn => fn && fn(error))
})
}
try {
// 包装传递进来的函数,传递resolve 和reject函数
exec(resolve, reject)
} catch (error) {
reject(error)
}
}
// 如果then必须返回一个promise对象,这也是能够链式调用的原因,
// 如果是pending状态 那么返回的promise状态决定了调用者promise的状态
then(onFullfill, onReject) {
// 当then后面传入的不是函数 会被转化为函数?
onFullfill = typeof onFullfill === 'function' ? onFullfill : value => value
onReject = typeof onReject === 'function' ? onReject : reason => reason
if (this.status === 'pending') {
return new simplePromise((resolve, reject) => {
this.fullfillCalls.push(onFullfill)
this.rejectCalls.push(onReject)
})
// 当返回fullfilled状态 则立即执行fullfillCalls队列
} else if (this.status === 'fullfilled') {
onFullfill(this.value)
// this.fullfillCalls.forEach(fn => fn && fn(this.value))
} else if (this.status === 'rejected') {
onReject(this.reason)
// this.rejectCalls.forEach(fn => fn && fn(this.reason))
}
}
}
// 首先传入的函数被包裹到exec调用then函数,返回一个promise,将then后面的第一个函数压栈
// 等待setTimeout任务完成调用resolve,完成状态转化和函数执行
new simplePromise((resolve, reject) =>{
setTimeout(() =>{
resolve(123)
})
}).then(value =>{
console.log(value)
})
手动添加方法
Promise.prototype.done(callback){
return this.then(
value => {this.then(callback()).then(()=>value}
reason => {this.then(callback()).then(() => throw reason)}
)
}
Array.prototype.add(number){
return Array.prototype.concat.call(this, number)
}
网友评论