【问题标题】:Reject a javascript Promise拒绝 javascript Promise
【发布时间】:2020-01-17 17:09:47
【问题描述】:

我想拒绝一个我没有建立的承诺。也就是说,我读过的例子描述了类似的东西:

const sample = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('fail promise');
    }, 1000);
});

1s 后拒绝sample。在我的情况下,我想要拒绝的承诺是作为外部 api 调用来的,那么我不能以这种方式拒绝。

我读过的另一种方法显示了如何将 promise 与使用 setTimeout 拒绝新 promise 的其他方法包装在一起。像这样的:

const timeout = new Promise(function(resolve, reject) {
    setTimeout(resolve, 1000, 'one');
});

const sample = new Promise(function(resolve, reject) {
    setTimeout(resolve, 5000, 'two');
});

return Promise.race([sample, timeout]);

在返回另一个承诺 1 秒后“拒绝”sample 的力量。这可以用来设置超时,但实际上它不会拒绝sample,只会返回另一个承诺,原始承诺会继续运行,直到它拒绝或自行解决。

我找不到如何正确拒绝没有库的承诺

【问题讨论】:

  • 你不能拒绝别人的承诺。 Promise 是故意这样设计的。只有有权访问 Promise executor 函数的 Promise 的创建者才能解决或拒绝它。相反,使用他们的结果(无论它是什么),然后从中创建您自己的结果。
  • 感谢您的回答,如果找到记录它的地方,请告诉我。事实上,我同意你的看法,因为 resolve/reject 方法只允许在创建 Promise 期间使用,但我会知道它是否记录在某个地方,我一直在寻找它,但我没有运气找到它。
  • 好吧,resolve、reject 和promise 的函数被传递给promise 执行器,它们不是promise 上的方法。这意味着它们仅可用于执行器回调函数内部的代码,除非该回调以某种方式使它们可用于外部世界。我只能向您指出 Promise 文档,该文档显示了 resolve()reject() 函数的传递位置,您将看到它们仅可用于该回调。 Promise 上的公共方法是 .then().catch().finally()
  • 仅供参考,在 99.9999% 的情况下,现有的 Promise 模型工作得很好,您可以从 executor 回调函数中解决或拒绝 Promise。偶尔,您希望能够从该回调之外控制自己的承诺。这个piece of code 展示了如何从常规承诺创建自己的延迟对象,然后可以从执行程序外部解决或拒绝该对象。你通常不需要这个,只能根据你自己的承诺来做。
  • 90% 的答案都在问题中。 1. 确保 'timeout' Promise 被拒绝; 2.来自Promise.race()返回的Promise链,即return Promise.race([sample, timeout]).then(data => doSomethingWith(data)).catch(error => /* timeout or other error from earlier in the chain will end up here */)。在实践中,.then().catch() 很可能被链接到调用者中的函数调用。

标签: javascript ecmascript-6 promise es6-promise


【解决方案1】:

为什么你需要拒绝他们的承诺?您关心的是为您的代码获得有用的结果,因此请编写代码来获得该结果。

将 API 调用封装在您自己的 Promise 中,并在 your Promise 上拒绝超时,如果该 API 在超时前产生结果,则传递 resolve

const attempt = new Promise( (resolve, reject) => {
  // run the actual API _and_ your rejection timeout concurrently:
  let rejected = false;

  const id = setTimeout(() => {
    rejected = true;
    reject(new Error('timeout');
  }), 1000);

  actualApiCall(some, input, args, here)
    .then(result => {
      if (rejected) return; // <- if we rejected via timeout, we no longer care.
      clearTimeout(id);     // <- always remember to properly clean up
      resolve(result);
     })
    .catch(e => {
      if (rejected) return;
      clearTimeout(id);
      reject(e)
    });
});

attempt
  .then(result => doSomethingWith(result))
  .catch(e => console.log('rejected:', e));

【讨论】:

  • 感谢您的回答。您的代码允许在等待 1 秒后继续 doingSomethingWith(...)。这很好,但是来自actualApiCall 的承诺会继续运行,直到它自己解决或拒绝。即使很难,它也不会做任何事情,因为rejected=true 它可以继续运行很长时间。就我而言,在“拒绝”(使用您的方法)之后,我将使用另一个参数再次调用 actualApiCall 几次,并且相同的行为可能会再次成功。
  • 我正在使用它来重播播放列表。如果一个视频需要很长时间才能开始,那么转到下一个。我正在使用 videoJS,问题是 play() 方法返回一个在没有自定义控件的情况下在内部解决/拒绝的承诺。使用您的方法,我可以加载另一个视频,但实际上 play() 承诺继续运行。在测试过程中,我看到在大量拒绝(使用类似的方法)之后 CPU 也增长了
  • 那么这就是我说“如果这是问题所在,你为什么不把它放在你的帖子中,这样人们就可以真正评论 那个 问题”?请更新您的帖子以提及您尝试使用的特定库,并记得相应地更新您的标签。
  • 我的问题很笼统,我试图给你一个用例只是为了弄清楚这个问题的用处。也就是说,我描述的问题并不特定于我给你作为例子的库。
  • 它实际上是特定于该库的。这是一个经典的 X/Y 问题。你的假设是错误的:你想中止一项任务。然而,这不是 Promise API 的一部分。所以你的图书馆需要有一种不同的方式来取消某些东西。
【解决方案2】:

我找不到如何正确拒绝没有库的承诺

首先,这对我来说似乎不是一个好方法,即使您可以执行以下操作,

const apiPromise = externalApi();

现在apiPromise 可以处于resolvedrejected 状态。在这两种情况下,您都可以抛出类似的错误,

const rejectedPromise = apiPromise.then(
  (fulfilledValue) => { throw "error" },
  (rejetedValue) => { throw "error" }
);
rejectedPromise.catch(err => console.log(err)); //logs "error"

阅读更多Promise.then()

【讨论】:

    猜你喜欢
    • 2021-09-23
    • 2016-09-18
    • 2016-02-19
    • 1970-01-01
    • 2018-10-08
    • 2016-11-10
    • 2017-07-22
    相关资源
    最近更新 更多