如何添加 polyfill 以支持 Edge 中的 finally()?
How to add a polyfill to support finally() in Edge?
我正在使用 axios 库并使用 then()、catch() 和 finally()。在 Chrome 中完美运行。但是 finally() 方法在 MS Edge 中不起作用。我研究了使用 polyfills 或垫片,但我迷路了。我没有使用 webpack 或转译,也不打算添加它们。我需要保持这个简单。如何添加 polyfill 以确保 finally() 在 Edge 中正常工作?谢谢!
除了下面详述的行为之外,这还应该处理 thenable 的 species
的传播:
Promise.prototype.finally = Promise.prototype.finally || {
finally (fn) {
const onFinally = callback => Promise.resolve(fn()).then(callback);
return this.then(
result => onFinally(() => result),
reason => onFinally(() => Promise.reject(reason))
);
}
}.finally;
此实现基于 finally()
and depends on then()
符合规范的记录行为:
A finally
callback will not receive any argument, since there's no reliable means of determining if the promise was fulfilled or rejected. This use case is for precisely when you do not care about the rejection reason, or the fulfillment value, and so there's no need to provide it.
Unlike Promise.resolve(2).then(() => {}, () => {})
(which will be resolved with undefined
), Promise.resolve(2).finally(() => {})
will be resolved with 2
.
Similarly, unlike Promise.reject(3).then(() => {}, () => {})
(which will be fulfilled with undefined
), Promise.reject(3).finally(() => {})
will be rejected with 3
.
Note: A throw
(or returning a rejected promise) in the finally
callback will reject the new promise with the rejection reason specified when calling throw()
.
当然还有等效行为的演示:
const logger = (label, start = Date.now()) => (...values) => {
console.log(label, ...values, `after ${Date.now() - start}ms`);
};
const delay = (value, ms) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});
// run test on native implementation
test('native');
// force Promise to use the polyfill implementation
Promise.prototype.finally = /* Promise.prototype.finally || */ {
finally (fn) {
const onFinally = callback => Promise.resolve(fn()).then(callback);
return this.then(
result => onFinally(() => result),
reason => onFinally(() => Promise.reject(reason))
);
}
}.finally;
// run test on polyfill implementation
test('polyfill');
function test (impl) {
const log = ordinal => state => logger(`${ordinal} ${impl} ${state}`);
const first = log('first');
// test propagation of resolved value
delay(2, 1000)
.finally(first('settled'))
.then(first('fulfilled'), first('rejected'));
const second = log('second');
// test propagation of rejected value
delay(Promise.reject(3), 2000)
.finally(second('settled'))
.then(second('fulfilled'), second('rejected'));
const third = log('third');
// test adoption of resolved promise
delay(4, 3000)
.finally(third('settled'))
.finally(() => delay(6, 500))
.then(third('fulfilled'), third('rejected'));
const fourth = log('fourth');
// test adoption of rejected promise
delay(5, 4000)
.finally(fourth('settled'))
.finally(() => delay(Promise.reject(7), 500))
.then(fourth('fulfilled'), fourth('rejected'));
}
.as-console-wrapper{max-height:100%!important}
感谢 @Bergi for his input on this answer. Please see ,如果您觉得此 post 有帮助,也请点赞。
我正在使用 axios 库并使用 then()、catch() 和 finally()。在 Chrome 中完美运行。但是 finally() 方法在 MS Edge 中不起作用。我研究了使用 polyfills 或垫片,但我迷路了。我没有使用 webpack 或转译,也不打算添加它们。我需要保持这个简单。如何添加 polyfill 以确保 finally() 在 Edge 中正常工作?谢谢!
除了下面详述的行为之外,这还应该处理 thenable 的 species
的传播:
Promise.prototype.finally = Promise.prototype.finally || {
finally (fn) {
const onFinally = callback => Promise.resolve(fn()).then(callback);
return this.then(
result => onFinally(() => result),
reason => onFinally(() => Promise.reject(reason))
);
}
}.finally;
此实现基于 finally()
and depends on then()
符合规范的记录行为:
A
finally
callback will not receive any argument, since there's no reliable means of determining if the promise was fulfilled or rejected. This use case is for precisely when you do not care about the rejection reason, or the fulfillment value, and so there's no need to provide it.Unlike
Promise.resolve(2).then(() => {}, () => {})
(which will be resolved withundefined
),Promise.resolve(2).finally(() => {})
will be resolved with2
.Similarly, unlike
Promise.reject(3).then(() => {}, () => {})
(which will be fulfilled withundefined
),Promise.reject(3).finally(() => {})
will be rejected with3
.Note: A
throw
(or returning a rejected promise) in thefinally
callback will reject the new promise with the rejection reason specified when callingthrow()
.
当然还有等效行为的演示:
const logger = (label, start = Date.now()) => (...values) => {
console.log(label, ...values, `after ${Date.now() - start}ms`);
};
const delay = (value, ms) => new Promise(resolve => {
setTimeout(resolve, ms, value);
});
// run test on native implementation
test('native');
// force Promise to use the polyfill implementation
Promise.prototype.finally = /* Promise.prototype.finally || */ {
finally (fn) {
const onFinally = callback => Promise.resolve(fn()).then(callback);
return this.then(
result => onFinally(() => result),
reason => onFinally(() => Promise.reject(reason))
);
}
}.finally;
// run test on polyfill implementation
test('polyfill');
function test (impl) {
const log = ordinal => state => logger(`${ordinal} ${impl} ${state}`);
const first = log('first');
// test propagation of resolved value
delay(2, 1000)
.finally(first('settled'))
.then(first('fulfilled'), first('rejected'));
const second = log('second');
// test propagation of rejected value
delay(Promise.reject(3), 2000)
.finally(second('settled'))
.then(second('fulfilled'), second('rejected'));
const third = log('third');
// test adoption of resolved promise
delay(4, 3000)
.finally(third('settled'))
.finally(() => delay(6, 500))
.then(third('fulfilled'), third('rejected'));
const fourth = log('fourth');
// test adoption of rejected promise
delay(5, 4000)
.finally(fourth('settled'))
.finally(() => delay(Promise.reject(7), 500))
.then(fourth('fulfilled'), fourth('rejected'));
}
.as-console-wrapper{max-height:100%!important}
感谢 @Bergi for his input on this answer. Please see