【问题标题】:Cancel JavaScript Promise取消 JavaScript 承诺
【发布时间】:2018-12-10 18:36:34
【问题描述】:

我正在尝试取消承诺,如下所示:

function example(cancel = Promise.reject()) {
    return new Promise((resolve, reject) => {
        const timer = setTimeout(() => resolve('jack-jack'), 5000);
        cancel.then((res) => {
            clearTimeout(timer);
            reject('cancelled'); 
        }, ()=>{})
    });
}
var cancel=Promise.reject(); 
example(cancel).then((res) => console.log('res handled:' + res)).catch((err) => console.log('err handled:' + err));
console.log('attempting cancellation of promise');
cancel=Promise.resolve();

但是我无法取消它。我在这里做错了什么?

【问题讨论】:

标签: javascript ecmascript-6 promise es6-promise


【解决方案1】:

您已将拒绝的承诺分配给变量,将拒绝的承诺传递给您的函数,并将已解决的承诺分配给变量。变量取的两个值是不相关的,你不能改变一个已解决的 Promise 的状态。

传递一个你可以解决的承诺:

let cancel;
let cancelPromise = new Promise((resolve) => {
    cancel = resolve;
});

example(cancelPromise).then(…).catch(…);
console.log('attempting cancellation of promise');
cancel();

function example(cancel = Promise.reject()) {
    return new Promise((resolve, reject) => {
        const timer = setTimeout(() => resolve('jack-jack'), 5000);
        cancel.then((res) => {
            clearTimeout(timer);
            reject('cancelled'); 
        }, ()=>{})
    });
}

let cancel;
let cancelPromise = new Promise((resolve) => {
    cancel = resolve;
});

example(cancelPromise)
    .then((res) => console.log('res handled:' + res))
    .catch((err) => console.log('err handled:' + err));
console.log('attempting cancellation of promise');
cancel();

【讨论】:

    【解决方案2】:

    因为你传递了被拒绝的承诺。如果您希望 cancel.then() 块运行,请传递已解决的承诺。

    function example(cancel = Promise.resolve()) {
      return new Promise((resolve, reject) => {
        console.log(cancel);
        const timer = setTimeout(() => {
          resolve('jack-jack'), 5000
        });
        cancel.then((res) => {
          console.log('CANCELLED');
          clearTimeout(timer);
          reject('cancelled');
        }, () => {})
      });
    }
    var cancel = Promise.resolve();
    example(cancel).then((res) => console.log('res handled:' + res)).catch((err) => console.log('err handled:' + err));
    console.log('attempting cancellation of promise');
    cancel = Promise.resolve();

    【讨论】:

    • 但是如果已经知道必须取消该过程,那么为什么 OP 还要调用 example 呢?
    【解决方案3】:

    在您的代码中,您已经向函数传递了一个完整的(被拒绝的)Promise。而cancel=Promise.resolve();attempting cancellation of promise 之后不会对传递给example 的promise 产生任何影响,因为您只是创建了一个新的resolved Promise。

    如果您想取消正在运行的进程,那么您可能需要选择这样的解决方案:

    function example(helper) {
      return new Promise((resolve, reject) => {
        helper.cancel = function() {
          clearTimeout(timer)
          reject('cancelled');
        }
        const timer = setTimeout(() => resolve('jack-jack'), 5000);
    
      });
    }
    var helper = {};
    example(helper).then((res) => console.log('res handled:' + res)).catch((err) => console.log('err handled:' + err));
    
    console.log('attempting cancellation of promise');
    helper.cancel()
    

    【讨论】:

      【解决方案4】:

      由于cancel设置为reject,那么then部分

      cancel.then((res) => { //you cannot use then for reject, as reject cannot be resolved.
          clearTimeout(timer);
           reject('cancelled'); 
      }, ()=>{})
      

      永远不会被执行,因此你必须解决它,而不是拒绝它

      function example(cancel = Promise.reject()) {
          return new Promise((resolve, reject) => {
              const timer = setTimeout(() => resolve('jack-jack'), 5000);
              cancel.then((res) => { //you cannot use then for reject
                  clearTimeout(timer);
                  reject('cancelled'); 
              }, ()=>{})
          });
      }
      
      var cancel = Promise.resolve(); // just change to resolve
      
      example(cancel).then((res) => console.log('res handled:' + res)).catch((err) => console.log('err handled:' + err));
      
      console.log('attempting cancellation of promise');
      cancel=Promise.resolve(); // this will have no effect as you have already passed a reject

      【讨论】:

      • 我猜 OP 想在调用 example 之后取消执行,因为否则调用 example 是没有意义的。
      • @t.niese。我猜他发布了一段代码只是为了澄清。他的实现可能会有所不同
      猜你喜欢
      • 1970-01-01
      • 2017-10-09
      • 1970-01-01
      • 2017-11-23
      • 2017-05-24
      • 2015-01-23
      • 2015-02-13
      • 2015-07-25
      相关资源
      最近更新 更多