我在使用我认为的异步函数时遇到了麻烦。我有一些端点指向主机,其中一些请求从我的登录数据中获取令牌,另一个获取请求使用该令牌检索有关我的个人资料的信息。
我认为我遇到的问题是登录获取请求在我的令牌实际保存到我的标头变量之前运行。 有人能够解释一种方法,让我可以在 api 发送任何其他请求之前等待收到令牌吗?
const fastify = require('fastify')({ logger: true });
const axios = require('axios');
const fs = require('fs');
require('dotenv').config();
const username = process.env.USERNAME
const password = process.env.PASSWORD
let token
const instance = axios.create({
baseURL: process.env.URL,
headers : {
'Authorization': `Bearer ${token}`
}
})
async function login() {
const response = await instance.post('/login', {username, password})
token = response.data['token'];
console.log(token);
}
async function me() {
const response = await instance.get('/me')
console.log(response.data);
}
login().then(me())
谢谢!
这是因为 JavaScript 的异步行为允许 login() 启动,但不一定在 me() 执行之前完成。
要解决此问题,您应该确保 me() 仅在 login() 函数完成并且令牌可用后运行。处理这个问题的正确方法是在异步函数中使用await 和login() 或链接.then() 方法。
以下是重构代码来解决问题的方法:
解决方案1:在异步函数中使用async/await
const fastify = require('fastify')({ logger: true });
const axios = require('axios');
const fs = require('fs');
require('dotenv').config();
const username = process.env.USERNAME;
const password = process.env.PASSWORD;
let token;
const instance = axios.create({
baseURL: process.env.URL,
headers: {
'Authorization': `Bearer ${token}`
}
});
async function login() {
try {
const response = await instance.post('/login', { username, password });
token = response.data['token'];
console.log(token);
} catch (error) {
console.error('Login failed:', error);
}
}
async function me() {
try {
const response = await instance.get('/me');
console.log(response.data);
} catch (error) {
console.error('Error fetching profile:', error);
}
}
// Create an async function to ensure login is done before making the next request
async function performRequests() {
await login(); // Wait for login to complete and token to be set
await me(); // Now you can safely make the request with the token
}
performRequests();
说明: login() 是一个异步函数,它从登录端点获取令牌。 me() 是另一个依赖于令牌的异步函数。 PerformRequests() 是一个异步函数,可确保 login() 在调用 me() 之前完成。 我们在login()和me()前面使用await来确保它们按顺序运行——me()在login()完成并设置令牌之前不会执行。 解决方案 2:使用 .then() 和 Promise 链 如果您更喜欢使用 .then() 而不是 async/await,您也可以链接承诺。方法如下:
const fastify = require('fastify')({ logger: true });
const axios = require('axios');
const fs = require('fs');
require('dotenv').config();
const username = process.env.USERNAME;
const password = process.env.PASSWORD;
let token;
const instance = axios.create({
baseURL: process.env.URL,
headers: {
'Authorization': `Bearer ${token}`
}
});
function login() {
return instance.post('/login', { username, password })
.then(response => {
token = response.data['token'];
console.log(token);
})
.catch(error => {
console.error('Login failed:', error);
});
}
function me() {
return instance.get('/me')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error('Error fetching profile:', error);
});
}
login().then(me); // Wait for login to complete, then call me
说明: login() 现在返回一个promise(由instance.post()返回),因此一旦login()成功解析,您就可以链接.then()来运行me()函数。 这是有效的,因为 .then() 确保 me() 仅在 login() 完成后运行。 任何一种解决方案都可以解决问题,但使用 async/await 通常更具可读性和更简洁,尤其是在处理多个异步操作时。