Javascript 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 |承诺)=>无效, 拒绝:(原因?:任何)=

我希望能够从Vue组件中取消已启动的承诺,特别是Vuex操作返回的承诺

我的用例是Vuex操作轮询端点的状态,如果用户执行某个操作(示例中的关闭函数),我希望能够取消轮询

我从另一个stackoverflow答案中创建了一个自定义CancelablePromise类,但它不适用于Vuex

可取消承诺类(来自)

导出类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'));
    }
}