Javascript Vuex行动取消承诺
我希望能够从Vue组件中取消已启动的承诺,特别是Vuex操作返回的承诺 我的用例是Vuex操作轮询端点的状态,如果用户执行某个操作(示例中的关闭函数),我希望能够取消轮询 我从另一个stackoverflow答案中创建了一个自定义CancelablePromise类,但它不适用于Vuex 可取消承诺类(来自)Javascript Vuex行动取消承诺,javascript,typescript,vue.js,promise,vuex,Javascript,Typescript,Vue.js,Promise,Vuex,我希望能够从Vue组件中取消已启动的承诺,特别是Vuex操作返回的承诺 我的用例是Vuex操作轮询端点的状态,如果用户执行某个操作(示例中的关闭函数),我希望能够取消轮询 我从另一个stackoverflow答案中创建了一个自定义CancelablePromise类,但它不适用于Vuex 可取消承诺类(来自) 导出类CancelablePromise扩展了Promise{ 私有onCancel:()=>无效; 建造师( 执行人:( 解决:(价值?:T |承诺)=>无效, 拒绝:(原因?:任何)=
导出类CancelablePromise扩展了Promise{
私有onCancel:()=>无效;
建造师(
执行人:(
解决:(价值?:T |承诺)=>无效,
拒绝:(原因?:任何)=>无效,
onCancel:(cancelHandler:()=>void)=>void
)=>无效
) {
让onCancel:()=>无效;
超级((rs,rj)=>
执行人(rs,rj,(ch:()=>无效)=>{
onCancel=ch;
})
);
this.onCancel=onCancel;
}
公共取消():无效{
if(this.onCancel){
这个。onCancel();
}
}
}
行动
async [SomeAction.foo]({ state, dispatch, commit, rootGetters }) {
const cancellablePromise = new CancellablePromise<any>((resolve, reject, onCancel) => {
const interval = setInterval(async () => {
const status = await dispatch(SomeAction.bar);
if (status === "goodstatus") {
clearInterval(interval);
resolve();
} else if (status === "badstatus") {
clearInterval(interval);
reject();
}
}, 2000);
onCancel(() => {
clearInterval(interval);
reject();
});
});
return cancellablePromise;
}
async[SomeAction.foo]({state,dispatch,commit,rootGetters}){
const cancelablepromise=new cancelablepromise,它似乎再次从操作返回的Promise
创建了一个new Promise
。我不太熟悉Typescript的类型系统,但除非我误读了这段代码,否则我认为我的cancelablepromise
在这里“丢失”
我怎样才能完成我想在这里做的事呢?延长承诺是杂乱无章的,没有必要的。这更正常
- 将承诺的
拒绝
方法公开给更广泛的世界(在承诺的构造函数之外),并在必要时调用它以使承诺采用其错误路径
- 将“取消承诺”与利益承诺竞争,但这在这里不是必需的,因为
setInterval
过程的承诺使拒绝
方法可用
像这样的东西应该可以(未经测试)
行动
async [SomeAction.foo]({ state, dispatch, commit, rootGetters }) {
let reject_, interval;
const promise = new Promise((resolve, reject) => {
reject_ = reject; // externalise the reject method
interval = setInterval(async () => {
const status = await dispatch(SomeAction.bar);
if (status === 'goodstatus') {
resolve();
} else if (status === 'badstatus') {
reject(new Error(status)); // for example
} else {
// ignore other states ???
}
}, 2000);
});
promise.cancel = reject_; // decorate promise with its own reject method.
return promise.always(() => { clearInterval(interval) }); // clear the interval however the promise settles (resolve() or reject() above, or promise.cancel() externally).
}
组成部分
data: (() => {
cancel: null
}),
async call() {
this.close(new Error('new call was made before previous call completed')); // may be a good idea
let promise = this.$store.dispatch(SomeAction.foo); // don't chain .then() yet otherwise the .cancel property is lost.
this.cancel = promise.cancel; // store the means to force-reject the promise;
return promise.then(response => { // now chain .then()
// do something
})
.catch(error => {
console.log(error);
throw error;
});
},
close(reason): void {
if (this.cancel) {
this.cancel(reason || new Error('cancelled'));
}
}
我想您可以将其添加到prototype中:Promise.prototype.cancel=…
?正如您所指出的,Vuex将您的cancelablepromise
包装为一个新的(不可取消的)承诺
,因此您不能直接从您的操作中访问您自己的承诺。除非您自己修补Vuex,否则我认为没有办法取消承诺。除了调用其取消()之外,您是否建议使用此.Promise
method?@Roamer-1888不,我不这么认为。为什么?这似乎与我原来的解决方案不起作用的原因不一样:dispatch
创建了一个新的承诺
,它包装了在行动中创建的承诺。也许我做错了什么事情,使它不起作用?哎哟!这让生活变得棘手。我会的der是否有其他的分派方法;直接调用Someaction.foo()
的方法?
async [SomeAction.foo]({ state, dispatch, commit, rootGetters }) {
let reject_, interval;
const promise = new Promise((resolve, reject) => {
reject_ = reject; // externalise the reject method
interval = setInterval(async () => {
const status = await dispatch(SomeAction.bar);
if (status === 'goodstatus') {
resolve();
} else if (status === 'badstatus') {
reject(new Error(status)); // for example
} else {
// ignore other states ???
}
}, 2000);
});
promise.cancel = reject_; // decorate promise with its own reject method.
return promise.always(() => { clearInterval(interval) }); // clear the interval however the promise settles (resolve() or reject() above, or promise.cancel() externally).
}
data: (() => {
cancel: null
}),
async call() {
this.close(new Error('new call was made before previous call completed')); // may be a good idea
let promise = this.$store.dispatch(SomeAction.foo); // don't chain .then() yet otherwise the .cancel property is lost.
this.cancel = promise.cancel; // store the means to force-reject the promise;
return promise.then(response => { // now chain .then()
// do something
})
.catch(error => {
console.log(error);
throw error;
});
},
close(reason): void {
if (this.cancel) {
this.cancel(reason || new Error('cancelled'));
}
}