JS:在导出内容之前调用异步函数

时间:2017-06-15 11:35:33

标签: javascript asynchronous async-await es6-modules ecmascript-next

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

我的第一次尝试:

const token = await sessionHandler.getToken();

export const httpService = axios.create({
    ...
    headers: {
        "auth-token": token
        ...
    }
});

当然这不起作用,因为await不在异步函数中。 所以我可以将它包装在异步函数中,对吧?不,因为我必须使用回调。那么我再也不会在顶层出口也不会有效。

最好的方法是什么?

2 个答案:

答案 0 :(得分:4)

这是不可能的。 必须以同步方式定义导出,并且在导出之前不能等待。

我建议您导出异步功能。如果您不希望每次都请求令牌,您可以考虑保存它:

let token;

export const createHttpService = async () => {
  token = token || await sessionHandler.getToken();
  return axios.create({
    /* ... */
    headers: {
        "auth-token": token
        /* ... */
    }
  });
};

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

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

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

或者,如果您确实希望在加载模块时需要令牌,则可以直接导出promise。但是,我建议对模块加载时的副作用保持警惕。

答案 1 :(得分:2)

如果httpService不能异步,那么我会使用interceptors来满足这种要求,如果令牌在第一次请求时没有准备好,那么拦截器将等到承诺完成。该令牌只会被请求一次。

const axios = require('axios')
const token = sessionHandler.getToken();

export const httpService = axios.create({
  ...
  headers: {
    ...
  }
});

httpService.interceptors.request.use(function(config) {
  return token.then(token => {
    config.headers['auth-token'] = token;
    return config;
  })
}, function(error) {
  console.dir(error)
  // Do something with request error
  return Promise.reject(error);
});

编辑我个人更喜欢,如果数据只是按需提供而不是包含,那么我会使用略有不同的版本:

const axios = require('axios')
let token;

export const httpService = axios.create({
  ...
  headers: {
    ...
  }
});

httpService.interceptors.request.use(function(config) {
  token = token || sessionHandler.getToken(); //request it only if not already requested.

  return token.then(token => {
    config.headers['auth-token'] = token;
    return config;
  })
}, function(error) {
  console.dir(error)
  // Do something with request error
  return Promise.reject(error);
});