【问题标题】:Does my solution make sense? Working with promises, timeouts, try/catch我的解决方案有意义吗?使用 Promise、超时、try/catch
【发布时间】:2019-08-07 13:53:53
【问题描述】:

我想找到一个有两个承诺的解决方案。第一个承诺必须完成。第二个承诺不一定要完成,但用户不应该在重定向发生之前等待特定的时间。

我已尝试创建解决方案,但由于我是新手,不知道如何测试此代码或查看它是否有效。真的很想看看其他人对这段代码为什么好或坏的看法,并愿意改进。

async function apiPromise(url) {
        try {
            const response = await fetch(url);
            const json = response.json(); 
            return {json}
        } catch (error) {
            console.error(error);
        }
}

// promise timeout wrapper race condition
function promiseTimeout(ms, promise) {
    // Create a promise that rejects in <ms> milliseconds
  let timeout = new Promise((resolve, reject) => {
    let id = setTimeout(() => {
      reject('Timed out in '+ ms + 'ms.')
    }, ms)
  })

  // Returns a race between our timeout and the passed in promise
  return Promise.race([
    promise,
    timeout
  ]).then(result => {
      clearTimeout(id);
      return result
  })
}

// let's assume this runs, componentDidMount
function setup() {
    let promises = [apiPromise('url'), timeoutPromise(5000, apiPromise('url'))]
    Promise.all(promises)
        .then(results => {
            // do whatever with the results array
        })
        .catch(error=> {
            console.error(error);
            window.location.href= '/redirect'
        })
}

apiPromise 函数用于尝试获取 URL。如果成功,它会解析,但随后 catch 语句会使用新的 Error 对象拒绝它

promiseTimeout 函数用于针对给定的承诺和超时创建竞争条件

setup 函数就像一个反应组件DidMount 或只是启动代码。

总而言之,我不确定是否: 1)我正确地写了apiPromise,并进行了适当的尝试和捕捉。这有意义吗? 2) 如果第二个承诺确实超时,我的 promise.all 是否会按预期工作,用户会被重定向?

【问题讨论】:

  • 第一个函数中的经典错误 ... Promise 构造函数反模式 ... fetch 返回一个 Promise,不要将它包装在 Promise 中 ... 停止阅读
  • 感谢您的输入,我将其更改为函数仅在函数中使用 try/catch 的位置,如果获取成功,则尝试返回带有数据的对象,如果失败控制台出错。问题:如果第二个 API 调用超时,那么我的设置函数中的捕获是否会起作用,然后用户被重定向?抱歉 - 我仍在学习并努力变得更好
  • Promise.all 要么全有,要么全无。一旦数组中的所有承诺都解决了,它就会解决,或者一旦其中一个被拒绝,它就会被拒绝。因此,如果您的第二个承诺失败,您将收到错误消息。所以catch块会被激活。
  • @Thuvarakan 我看过一些帖子解释如何让承诺进入挂起状态,然后看看它是否会履行或拒绝 - 然后他们抓住拒绝,然后按顺序将其返回给 Promise.all让它成功运行某些正确解决的承诺,而其他承诺被拒绝。根据您的经验,这行得通吗?如果您有多个请求,您是否只是将它们链接起来(即异步等待?)
  • @Yunjichu 是的,如果您在内部处理错误,那么 promise.all 将正常工作。但在您的情况下,promiseTimeout 函数正在返回拒绝。那么你需要在返回的promise中添加一个catch状态并在catch中解析promise。 promiseDemo.catch(error => null)

标签: javascript asynchronous promise race-condition


【解决方案1】:

Promise.all() 总是等待每个 Promise 返回一些东西,如果一个失败,它不会等待其他人完成,而是会抛出一个错误。

我要做的是,将超时设置为处理 fetch() 的函数,然后在 fetch 及时完成时将其销毁。否则重定向会将用户转发到任何地方。此外,在 fetch() 确实及时完成但抛出错误的情况下,您可能希望将用户转发到不同的 url,因此需要 redirect() 函数。

async function apiPromse(url) {
  const timeout = timeOut(() => redirect(url), ms);    
  try {
    const response = await fetch(url);
    // Destroy timeout if a response is received, otherwise redirect
    clearTimeout(timeout);
    return await response.json();
  } catch (error) {
    console.log(error);
    // Redirect to another url in case the fetch() fails
    clearTimeout(timeout);
    redirect(url);
  }
}

function redirect(url) {
  window.location.href(url)
}

async function setup() {
  const apiResult = await this.apiPromise('url');
  // Do Stuff with apiResult
}

【讨论】:

    猜你喜欢
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 2013-05-13
    • 2011-02-06
    • 1970-01-01
    • 2020-02-11
    • 2023-03-03
    相关资源
    最近更新 更多