使用 extends 对内置的 Promise 进行子类化
Subclassing the Promise built-in using extends
我想将 cancel
方法添加到 Promise
内置的子类。为什么这不起作用?
class CancellablePromise extends Promise {
constructor(executor) {
let cancel = null
super((resolve,reject) => {
cancel = reject
executor(resolve, reject)
})
this.cancel = cancel
}
}
const p = new CancellablePromise((resolve) => setTimeout(resolve, 1000))
.then(() => console.log('success'))
.catch((err) => console.log('rejected', err))
p.cancel() // Uncaught exception
答案是Symbol.species
吗?
问题是 then
、catch
和 finally
创建并 return 一个 new 承诺,并且他们创建的新承诺 return 上面没有 cancel
方法。
要解决这个问题,您必须重写 then
,以便它将 cancel
从当前实例复制到新实例:
class CancellablePromise extends Promise {
constructor(executor) {
let cancel = null;
super((resolve,reject) => {
cancel = reject;
executor(resolve, reject);
});
this.cancel = cancel;
}
then(onFulfilled, onRejected) {
const p = super.then(onFulfilled, onRejected);
p.cancel = this.cancel;
return p;
}
}
const p = new CancellablePromise((resolve) => setTimeout(resolve, 1000))
.then(() => console.log('success'))
.catch((err) => console.log('rejected', err));
p.cancel();
您不需要执行 catch
或 finally
,它们都是使用调用 then
(根据规范)定义的。
我应该指出,关于可取消的承诺有很多细微差别,我没有详细讨论。可能值得深入阅读 Ben Lesh 的 Domenic Denicola's old (now withdrawn) cancellable promises proposal and this article。
实际上,then
方法returns是当前promiseclass的一个新实例,所以p.cancel
方法会在返回的promise上定义,但是它指的是链中的最后一个承诺(catch
链)。
取消承诺比仅仅拒绝链中的第一个承诺要困难得多。至少,您需要拒绝链中最深的未决承诺并清理内部长期操作,如请求、流、setTimeout 等。
它们应该看起来像这样:
import CPromise from "c-promise2";
const delay= (ms, value)=>{
return new CPromise((resolve, reject, {onCancel}) => {
const timer = setTimeout(resolve, ms, value);
onCancel(() => {
log(`clearTimeout`);
clearTimeout(timer);
})
})
}
const p= delay(1000, 123).then(console.log);
p.cancel();
我想将 cancel
方法添加到 Promise
内置的子类。为什么这不起作用?
class CancellablePromise extends Promise {
constructor(executor) {
let cancel = null
super((resolve,reject) => {
cancel = reject
executor(resolve, reject)
})
this.cancel = cancel
}
}
const p = new CancellablePromise((resolve) => setTimeout(resolve, 1000))
.then(() => console.log('success'))
.catch((err) => console.log('rejected', err))
p.cancel() // Uncaught exception
答案是Symbol.species
吗?
问题是 then
、catch
和 finally
创建并 return 一个 new 承诺,并且他们创建的新承诺 return 上面没有 cancel
方法。
要解决这个问题,您必须重写 then
,以便它将 cancel
从当前实例复制到新实例:
class CancellablePromise extends Promise {
constructor(executor) {
let cancel = null;
super((resolve,reject) => {
cancel = reject;
executor(resolve, reject);
});
this.cancel = cancel;
}
then(onFulfilled, onRejected) {
const p = super.then(onFulfilled, onRejected);
p.cancel = this.cancel;
return p;
}
}
const p = new CancellablePromise((resolve) => setTimeout(resolve, 1000))
.then(() => console.log('success'))
.catch((err) => console.log('rejected', err));
p.cancel();
您不需要执行 catch
或 finally
,它们都是使用调用 then
(根据规范)定义的。
我应该指出,关于可取消的承诺有很多细微差别,我没有详细讨论。可能值得深入阅读 Ben Lesh 的 Domenic Denicola's old (now withdrawn) cancellable promises proposal and this article。
实际上,then
方法returns是当前promiseclass的一个新实例,所以p.cancel
方法会在返回的promise上定义,但是它指的是链中的最后一个承诺(catch
链)。
取消承诺比仅仅拒绝链中的第一个承诺要困难得多。至少,您需要拒绝链中最深的未决承诺并清理内部长期操作,如请求、流、setTimeout 等。
它们应该看起来像这样:
import CPromise from "c-promise2";
const delay= (ms, value)=>{
return new CPromise((resolve, reject, {onCancel}) => {
const timer = setTimeout(resolve, ms, value);
onCancel(() => {
log(`clearTimeout`);
clearTimeout(timer);
})
})
}
const p= delay(1000, 123).then(console.log);
p.cancel();