JS:在导出某些东西之前调用异步函数

san*_*oco 3 javascript asynchronous async-await ecmascript-next es6-modules

我需要调用一个异步函数来获取我的身份验证令牌。在导出中,我想包含此 fn 的返回值。

我的第一次尝试:

const token = await sessionHandler.getToken();

export const httpService = axios.create({
    ...
    headers: {
        "auth-token": token
        ...
    }
});
Run Code Online (Sandbox Code Playgroud)

当然这不起作用,因为await它不在异步函数中。所以我可以把它包装在一个异步函数中,对吗?不,因为我必须使用回调。再说一次,我不会在顶级导出,这也不起作用。

解决这个问题的最佳方法是什么?

Que*_*Roy 7

这不可能。导出必须以同步方式定义,您不能在导出之前等待某些东西。

我建议您导出一个异步函数。如果您不想每次都请求令牌,您可以考虑保存它:

let token;

export const createHttpService = async () => {
  token = token == null ? await sessionHandler.getToken() : token;
  return axios.create({
    /* ... */
    headers: {
        "auth-token": token
        /* ... */
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

但是,如果这对您来说是可以接受的,我想我更愿意将此令牌的请求分开,并让模块的使用者将其传回createHttpService(从而负责保存它)。

export const getToken = () => sessionHandler.getToken();

export const createHttpService = (token) => {
  return axios.create({
    /* ... */
    headers: {
        "auth-token": token
        /* ... */
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

或者,如果您真的想在模块加载时需要令牌,您可以直接导出承诺。但是,我建议警惕模块加载时的副作用。


t.n*_*ese 3

如果httpService不能是异步的,那么我将用于interceptors这种要求,如果令牌在第一个请求时没有准备好,那么拦截器将等待直到承诺完成。该令牌将仅被请求一次。

\n\n
const axios = require('axios')\nconst token = sessionHandler.getToken();\n\nexport const httpService = axios.create({\n  ...\n  headers: {\n    ...\n  }\n});\n\nhttpService.interceptors.request.use(function(config) {\n  return token.then(token => {\n    config.headers['auth-token'] = token;\n    return config;\n  })\n}, function(error) {\n  console.dir(error)\n  // Do something with request error\n  return Promise.reject(error);\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑就我个人而言,我更喜欢仅按需请求数据而不是包含数据,因此我会使用略有不同的版本:

\n\n
const axios = require('axios')\nlet token;\n\nexport const httpService = axios.create({\n  ...\n  headers: {\n    ...\n  }\n});\n\nhttpService.interceptors.request.use(function(config) {\n  token = token ||\xc2\xa0sessionHandler.getToken(); //request it only if not already requested.\n\n  return token.then(token => {\n    config.headers['auth-token'] = token;\n    return config;\n  })\n}, function(error) {\n  console.dir(error)\n  // Do something with request error\n  return Promise.reject(error);\n});\n
Run Code Online (Sandbox Code Playgroud)\n