【问题标题】:Reading token from AsyncStorage before a fetch call在 fetch 调用之前从 AsyncStorage 读取令牌
【发布时间】:2020-05-12 05:48:38
【问题描述】:

在我的ReactNative 应用程序中,我试图想出一个很好的模式来读取我存储在AsyncStorage 中的access_token 并在fetch 调用中使用它。

换句话说,我想创建一个使用某种类型的包装器的模式,以确保fetch 调用始终具有它需要的access_token。所以执行顺序应该总是:

调用 Fetch 调用 -> 从 AsyncStorage 和 Prep Header 获取令牌 -> 执行 Fetch 调用

我想出了以下代码,但看起来我在使用 AsyncStorageAsync 部分时遇到了问题,而且我的 fetch 呼叫在没有令牌的情况下发出。

这是我的fetch 电话:

export const someApiCall = (request) => {

   const url = 'https://myapi.com/add';

   return (dispatch) => fetch(url, fetchOptionsPost(request))
        .then((response) => {

            if (response.ok && response.status === 200) {

                // Got data. Dispatch some action

            }
        })
}

在这里,我使用辅助函数来准备标题等。这是fetchOptionsPost() 的样子:

export const fetchOptionsPost = (request) => {

    getAccessToken()
        .then(token => {

            return {
                method: 'POST',
                mode: 'cors',
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": "Bearer " + token
                },
                body: JSON.stringify(request)
            }
       });
};

getAccessToken() 函数只是从AsyncStorage 读取它,如下所示:

export const getAccessToken = async () => {

    return await AsyncStorage.getItem("access_token");
}

这种模式不起作用,API 调用在没有令牌的情况下发出。

我还想提一下,如果我在 fetchOptionsPost() 方法中对令牌进行硬编码,一切正常。显然,这里的问题是 fetchOptionsPost() 没有返回任何内容。

我能做些什么来确保我的fetchOptionsPost 中始终有我的令牌?

【问题讨论】:

  • 您是否将访问令牌添加到 AsyncStorage 中?如果是这样,你在哪里设置?
  • 我确实有一个单独的函数来处理保存令牌。我检查以确保令牌已存储,因此那里没有问题。问题似乎与代码流有关。 JavaScript 在执行 fetch 调用之前根本不会等到检索到令牌。

标签: javascript react-native fetch asyncstorage


【解决方案1】:

您可以在someApiCall 函数中添加token 调用。还可以在函数内部创建选项。函数是异步的,所以 fetch 只在获取令牌结果后运行

更新

const fetchOptionsPost = (token) =>{
  return ({
    method: 'POST',
    mode: 'cors',
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer " + token
    }
  })
}

export const someApiCall = async(request) => {
  const token = await AsyncStorage.getItem("access_token");
  const url = 'https://myapi.com/add';

  fetch(url, fetchOptionsPost(token))
    .then(response=>response.json())
    .then((data)=>{
       // call the dispatch here
      })
}

为什么在主函数内部使用异步

AsyncStorage 只有异步回调。如果您将 AsyncStorage 设置为单独的函数,则应该为这两个函数调用 async。这就是为什么我在父异步函数中添加了 with 并将令牌传递给 fetchOptionsPost

【讨论】:

  • 那么我必须在每个fetch 调用中重复此代码。为了简化我的 API 调用,我创建了 fetchOptionsPost() 函数。
  • 我想我试过了,但没用。让我再试一次。
  • 这给了我一个错误,上面写着:“操作必须是普通对象。使用自定义中间件进行异步操作。”
  • 我认为您正在使用 redux。对于 redux 异步调用 github.com/reduxjs/redux-thunk 。检查代码沙箱是否使用令牌codesandbox.io/s/vibrant-lake-d9wxs
  • 是的,我确实使用 Redux 和 Redux Thunk。让我研究你的代码。看起来和我正在做的很相似。
【解决方案2】:

这是我想出的,似乎工作正常。对此代码的任何建议或改进,我仍将不胜感激。

首先,这是我的fetch 调用现在的样子。我将它包裹在 getAccessToken() 函数中,这是一个 async 调用,但因为我使用的是 redux-thunk,所以我能够做到这一点。

export const someApiCall = (request) => {

   const url = 'https://myapi.com/add';

   return (dispatch) => getAccessToken()
        .then(token => {
            fetch(url, fetchOptionsPost(request, token))
                .then((response) => {

                     if (response.ok && response.status === 200) {

                          // Got data. Dispatch some action

                      }
                 })
        })
}

我稍微更改了我现在接受令牌的 fetchOptionsPost() 辅助函数。它现在也更强大了。如果它没有得到一个令牌,它只是省略了标题中的Authorization 部分。我选择了这种方法,因为对我的 API 后端的某些调用不需要身份验证。 isValidString() 也是我创建的另一个帮助验证函数,以确保我得到一个有效的字符串。它根据输入的字符串值返回TRUEFALSE 响应:

export const fetchOptionsPost = (data, token = null) => {

    if (isValidString(token)) {

        return {
            method: 'POST',
            mode: 'cors',
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + token
            },
            body: JSON.stringify(data)
        }
    } else {

        return {
            method: 'POST',
            mode: 'cors',
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(data)
        }
    }
};

最后,getAccessToken() 函数并没有真正改变,但它是:

export const getAccessToken = async () => {

    return await AsyncStorage.getItem("access_token");
}

正如我所说,如果有任何关于进一步改进此代码的 cmets 或建议,我将不胜感激。

希望这对其他人有用。

【讨论】:

    【解决方案3】:

    使用 Async 和 await 方法并在每次调用之前获取令牌。

    async ()=>{
    let token =await getTokenFromLocal();
    return (dispatch) => fetch(url, fetchOptionsPost(request))
            .then((response) => {
    
                if (response.ok && response.status === 200) {
    
                    // Got data. Dispatch some action
    
                }
            })
    } 
    

    【讨论】:

      猜你喜欢
      • 2019-11-26
      • 2019-11-23
      • 2023-04-07
      • 1970-01-01
      • 2023-01-30
      • 2020-09-20
      • 1970-01-01
      • 2019-04-20
      • 2021-08-31
      相关资源
      最近更新 更多