几个获取调用的执行顺序

问题描述 投票:0回答:1

我想做的是:从我的单页应用程序中,使用 fetch 从 API 获取数据。如果 JWT 过期,请向 API 请求新的 JWT,然后重新请求数据。

我尝试用 3 个函数来实现它:

getData
调用
fetchData
。如果
fetchData
返回
JWT expired
消息,则调用函数
getjwt
(也在
getdata
内)和 then(仅然后)
fetchData
again.

应用程序调用

getData
在页面加载时——但这与这里无关

我有一个功能

getjwt

async function getjwt() {
// posts a refresh token and gets a jwt in headers
let adresse = `${baseUrl}/auth/getjwt`
let headers = { 'Content-Type': 'application/json' }

postData(adresse, refresh.value, headers)
.then((response) => {
  if (response.status === 200) {
    jwt.value = response.headers.get('__auth__')  
  }
})
.catch((err) => alert(err))
}

和功能

fetchData
getData

async function fetchData (url = '', headers = {}) {
  let r = await fetch(url, {
    method: 'GET', 
    mode: 'cors', 
    cache: 'no-cache', 
    credentials: 'include', 
    headers: headers,
    redirect: 'follow', 
    referrerPolicy: 'no-referrer', 
  })
  return r
}

async function getData(url = '', headers = {}) {
  let r = await fetchData(url, headers)
  if (r.status === 409) {
    console.log("Oh no! My token has expired.")
    getjwt()
    let r = await fetchData(url, headers)
    return r.json()
  } 
  return r.json()
}

故意地,第一次调用 fetchData 时,jwt 已过期。

getjwt
被调用并且 jwt 得到正确更新(在 Pinia 商店中)。但是:执行顺序是:
getData
被调用两次,然后
getjwt
被调用。

也许我遗漏了一些关于异步操作和 Promise 的东西,但是我怎么能强制调用

getjwt
并在
getData
第二次被调用之前完成获取新的 jwt。

javascript jwt es6-promise fetch-api asynchronous-javascript
1个回答
1
投票

getJwt
函数的问题在于它返回的承诺不会等待其中的异步操作完成。结果,它返回的承诺得到解决before
postData
完成。

您可以通过返回

postData
的承诺来解决此问题,如下所示:

async function getjwt() {
  ...

  return postData(...)
    .then((response) => {
      ...
    })
    .catch((err) => {
      ...
      throw err;
    });
}

return
调用之前添加一个
postData
可以解决问题,因为
return
确保
getJwt
函数返回的承诺得到 resolved
return postData(...)
返回的承诺。一个承诺
p1
解决另一个承诺
p2
只是意味着承诺
p1
将等待
p2
解决(履行或拒绝)。如果
p2
满足,则
p1
以相同的值满足。如果
p2
被拒绝,
p1
也会以相同的拒绝原因被拒绝。

注意

catch
方法的变化。需要
throw err
来避免隐含地将承诺拒绝转换为承诺实现.

由于您没有在函数内部使用

await
关键字,您不妨从函数签名中删除
async
关键字。

最后,要使其工作,您需要

await
调用
getJwt
函数内部的
getData
函数。

async function getData(url = '', headers = {}) {
  ...
  if (r.status === 409) {
    ...
    await getjwt()
    ...
  } 
  ...
}

我会通过以下两项改进来重构您的代码:

  • 省略
    catch
    方法调用,在调用
    getJwt
    函数的函数中处理错误
  • 使用
    async-await
async function getjwt() {
  // posts a refresh token and gets a jwt in headers
  let adresse = `${baseUrl}/auth/getjwt`;
  let headers = { 'Content-Type': 'application/json' };

  const response = await postData(adresse, refresh.value, headers);

  if (response.status === 200) {
    jwt.value = response.headers.get('__auth__');
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.