-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 64 题:模拟实现一个 Promise.finally #109
Comments
window.Promise && !('finally' in Promise) && !function() {
Promise.prototype.finally = function(cb) {
cb = typeof cb === 'function' ? cb : function() {};
var Fn = this.constructor; // 获取当前实例构造函数的引用
// 接受状态:返回数据
var onFulfilled = function(data) {
return Fn.resolve(cb()).then(function() {
return data
})
};
// 拒绝状态:抛出错误
var onRejected = function(err) {
return Fn.resolve(cb()).then(function() {
throw err
})
};
return this.then(onFulfilled, onRejected);
}
}();
/*********************** 测试 ***********************/
const p = new Promise((resolve, reject) => {
console.info('starting...');
setTimeout(() => {
Math.random() > 0.5 ? resolve('success') : reject('fail');
}, 1000);
});
// 正常顺序测试
p.then((data) => {
console.log(`%c resolve: ${data}`, 'color: green')
})
.catch((err) => {
console.log(`%c catch: ${err}`, 'color: red')
})
.finally(() => {
console.info('finally: completed')
});
// finally 前置测试
p.finally(() => {
console.info('finally: completed')
})
.then((data) => {
console.log(`%c resolve: ${data}`, 'color: green')
})
.catch((err) => {
console.log(`%c catch: ${err}`, 'color: red')
}); |
window.Promise.prototype = {
finally: function(callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
}
} 抄了个... |
为什么需要Promise.resolve(callback()).then(() => value) |
Promise.prototype.finally = function(callback) {
return this.then(
() => {
callback();
},
() => {
callback();
}
);
}; |
Promise.prototype.finally = function(callback){
const constructor = this.constructor
return this.then(value => {
return constructor.resolve(callback()).then(() => value)
}),
reason => {
return constructor.resolve(callback()).then(() => throw reason)
}
} |
因为callback如果是个异步操作,返回promise呢.希望等callback执行完再接着执行 |
https://github.com/taylorhakes/promise-polyfill/blob/master/src/finally.js finally是一个关键字,在IE低版本会引发解析错误,若兼容IE不能直接object.key语法. Promise.prototype['finally'] = function (callback) {
var constructor = this.constructor;
return this.then(
function(value) {
// @ts-ignore
return constructor.resolve(callback()).then(function() {
return value;
});
},
function(reason) {
// @ts-ignore
return constructor.resolve(callback()).then(function() {
// @ts-ignore
return constructor.reject(reason);
});
}
);
} |
看了这个问题才知道,原来 promise 的 finally 只是不管成功还是失败都会执行而已,而不会永远最后执行😂 new Promise((resolve, reject) => {
resolve();
}).finally(() => {
console.log('finally1');
}).then(() => {
console.log('then');
}).finally(() => {
console.log('finally2');
}); finally1
then
finally2 |
想问下,这里先通过P缓存this.constructor,后面再通过P.resolve的方式调用是有什么目的么,为什么不是直接 |
来个简洁版的: finally(callback) {
return this.then(
(res) => {
callback();
return res;
},
(err) => {
callback();
return err;
}
);
} |
看一个多月,还是没看懂,哪位大神能逐句解释一下 |
同问 |
我觉得是为了兼容那些自定义的Promise版本。比如说可以自己实现一个Promise叫MyPromise,像resolve和reject这些静态方法都是挂载在MyPromise上的。通过这样let P = this.constructor;写,兼容性更好吧。 |
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value, () => value),
reason => P.resolve(callback()).then(() => { throw reason }, () => {throw reason})
);
}; 如上在阮大神关于 finally 的写法中补充了一点。不知是否正确,欢迎探讨和学习。 callback 可能存在返回 promise,而该 promise 如果 reject,P.resolve 就会 reject,如果 P.resolve().then() 没有设置第二个回调,那么 this.then 的最终状态将是 reject 的状态,这与 es6 中所表现出来的 finally 的行为不一致。 如下是 es6 所表现的行为: new Promise((resolve, reject) => resolve(111)).finally(Promise.reject(222)) // 此时 es6 表现的行为状态为 resolve(111),而非 reject(222) |
@webfool new Promise((resolve, reject) => resolve(111))
.finally(Promise.reject(222)) // Promise {<resolved>: 111} 之所以最终返回的 如果对代码进行小小修改, 就发现 @lvtraveler 实现的 new Promise((resolve, reject) => resolve(111))
.finally(() => Promise.reject(222)) // Promise {<rejected>: 222} 现在再解释为什么你的代码得到 在规范中对这种传给 Promise.prototype.finally = function(onFinally) {
if (typeof onFinally !== 'function') {
return this.then(onFinally, onFinally)
}
// ...
} 那么 对于在
注: 这里没有给出 ES6 规范中对于 所以代码最后相当于: Promise.prototype.finally = function(onFinally) {
if (typeof onFinally !== 'function') {
return this.then() // 注: bluebird 也是这么实现的: https://github.com/petkaantonov/bluebird/blob/master/src/finally.js#L93
}
// ...
} 对于
根据对规范的理解, 具体的执行行为用代码表示为: Promise.prototype.finally = function(onFinally) {
if (typeof onFinally !== 'function') {
return this.then(
val => val,
reason => {
throw reason
}
)
}
// ...
} 再回到最初你的代码, 就知道最终 |
第一步获取构建函数,这里constructor就是获取,为什么用这个呢?主要是以前的promise实现有第三方的存在 |
有一点不明白,为什么异常处理要写在then的第二个参数里,而不是用catch方法 |
这里都不需要有 let P = this.constructor; 这一句了吧 |
Promise._finally = function(cb) {
return this.then(value => { cb(); return value }, err => { cb(); throw err})
} |
Promise.prototype.myFinally = function (func) { |
PromiseA.prototype.finally = (fn) => {
// 保证了fn执行在前.. 但是有点绕
return this.then((param)=>{
// 万一 fn reject了
return PromiseA.resolve(fn()).then(()=>param, ()=>param);
}, (err) =>{
// 万一 fn reject了
return PromiseA.resolve(fn()).then(()=>{
throw err;
}, ()=>{
throw err;
});
})
} |
finally (cb) {
return this.then(
value => Promise.resolve(cb()).then(() => value),
reason => Promise.resolve(cb()).then(() => { throw reason })
);
} |
你这样是不是把prototype都覆盖了 |
Promise.prototype.myFinally = async function (cb) {
const pr = this;
try {
await pr;
} finally {
cb && cb();
}
};
const start = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const temp = Math.round(Math.random());
if (temp > 0.5) {
resolve(temp);
} else {
reject(temp);
}
}, 2000);
});
};
start()
.then((res) => {
console.log("res", res);
})
.catch((err) => {
console.log("err", err);
})
.myFinally(() => {
console.log("finally");
}); |
|
你不说,我都没仔细注意到。。。 |
Promise.prototype.finally = function (callback) {
return this.then(
r => Promise.resolve(callback()).then(() => r),
e => Promise.resolve(callback()).then(() => { throw e })
)
} |
你不说,我都没注意到,招你这样说,这就是个普通函数而已 |
这样应该没什么问题吧,直接this也不用管是引入的还是默认的,cb也简单处理了一下,也能传递数据或者错误 Promise.prototype.finally = function(cb) {
cb = typeof cb === 'function' ? cb : () => cb
return this.then(cb, cb)
} |
The text was updated successfully, but these errors were encountered: