JS:在导出某些东西之前调用异步函数
JS: Call async function before exporting something
我需要调用一个异步函数来获取我的授权令牌。在导出中,我想包含此 fn 的返回值。
我的第一次尝试:
const token = await sessionHandler.getToken();
export const httpService = axios.create({
...
headers: {
"auth-token": token
...
}
});
当然这不起作用,因为 await
不在异步函数中。
所以我可以把它包装在一个异步函数中,对吧?不,因为我必须使用回调。然后我又不会在顶层导出,这也不起作用。
解决这个问题的最佳方法是什么?
这是不可能的。
导出必须以同步方式定义,不能在导出前等待。
我建议您导出一个异步函数。如果不想每次都请求token,可以考虑保存:
let token;
export const createHttpService = async () => {
token = token == null ? await sessionHandler.getToken() : token;
return axios.create({
/* ... */
headers: {
"auth-token": token
/* ... */
}
});
};
但是,如果这对您来说可以接受,我想我更愿意将此令牌的请求分开,让模块的使用者将其传回给 createHttpService
(从而负责保存它).
export const getToken = () => sessionHandler.getToken();
export const createHttpService = (token) => {
return axios.create({
/* ... */
headers: {
"auth-token": token
/* ... */
}
});
};
或者,如果您真的想在模块加载时需要令牌,您可以直接导出承诺。但是,我建议要警惕模块加载时的副作用。
如果 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);
});
我需要调用一个异步函数来获取我的授权令牌。在导出中,我想包含此 fn 的返回值。
我的第一次尝试:
const token = await sessionHandler.getToken();
export const httpService = axios.create({
...
headers: {
"auth-token": token
...
}
});
当然这不起作用,因为 await
不在异步函数中。
所以我可以把它包装在一个异步函数中,对吧?不,因为我必须使用回调。然后我又不会在顶层导出,这也不起作用。
解决这个问题的最佳方法是什么?
这是不可能的。 导出必须以同步方式定义,不能在导出前等待。
我建议您导出一个异步函数。如果不想每次都请求token,可以考虑保存:
let token;
export const createHttpService = async () => {
token = token == null ? await sessionHandler.getToken() : token;
return axios.create({
/* ... */
headers: {
"auth-token": token
/* ... */
}
});
};
但是,如果这对您来说可以接受,我想我更愿意将此令牌的请求分开,让模块的使用者将其传回给 createHttpService
(从而负责保存它).
export const getToken = () => sessionHandler.getToken();
export const createHttpService = (token) => {
return axios.create({
/* ... */
headers: {
"auth-token": token
/* ... */
}
});
};
或者,如果您真的想在模块加载时需要令牌,您可以直接导出承诺。但是,我建议要警惕模块加载时的副作用。
如果 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);
});