JavaScript如何等待API认证请求完成后执行后续接口调用
Hey there! This is such a common pitfall when you’re first working with asynchronous JavaScript—totally get why this tripped you up. Let’s walk through exactly how to make sure your getDevice call waits for that access token to be ready before running.
Why This Happens
First, let’s clarify the root issue: Your token-fetching function is asynchronous (it’s probably using fetch, axios, or another library that returns a Promise). JavaScript doesn’t pause execution to wait for async operations to finish by default—so when getDevice runs, the token hasn’t been fetched yet, hence the undefined value.
Solution 1: Use async/await (Most Readable)
This is the cleanest approach for modern JavaScript, since it lets you write async code that reads like synchronous code.
Step 1: Update Your Token Fetch Function to Return a Promise
First, make sure your authentication function in api.js explicitly returns the token (wrapped in a Promise, which async functions do automatically):
// api.js export async function fetchAccessToken() { try { const authResponse = await fetch("https://your-auth-api.com/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ // Add your auth credentials here (e.g., API key, device ID) apiKey: "your-api-key", deviceInfo: { /* ... */ } }) }); if (!authResponse.ok) throw new Error("Auth failed: " + authResponse.statusText); const authData = await authResponse.json(); return authData.access_token; // Return the token once fetched } catch (err) { console.error("Failed to get access token:", err); throw err; // Re-throw so the caller can handle the error } }
Step 2: Wait for the Token in getDevice
Now in device.js, use await to pause execution until the token is ready before making your device request:
// device.js import { fetchAccessToken } from "./api.js"; export async function getDevice(deviceId) { try { // Wait here until the token is fetched const accessToken = await fetchAccessToken(); const deviceResponse = await fetch(`https://your-api.com/devices/${deviceId}`, { headers: { "Authorization": `Bearer ${accessToken}`, // Use the now-ready token "Content-Type": "application/json" } }); if (!deviceResponse.ok) throw new Error("Failed to fetch device: " + deviceResponse.statusText); return deviceResponse.json(); } catch (err) { console.error("Error fetching device:", err); throw err; } }
Step 3: Call getDevice Correctly
When you use getDevice, you’ll need to either await it inside an async function or use .then():
// Example usage in your main code async function initApp() { try { const myDevice = await getDevice("device-123"); console.log("Fetched device:", myDevice); // Do something with the device data } catch (err) { // Handle any errors from auth or device fetch } } initApp();
Solution 2: Use Promise .then() Chains
If you prefer not to use async/await, you can chain Promises to enforce the order of operations:
// api.js export function fetchAccessToken() { return fetch("https://your-auth-api.com/token", { // Same auth config as before }) .then(authResponse => { if (!authResponse.ok) throw new Error("Auth failed"); return authResponse.json(); }) .then(authData => authData.access_token); } // device.js import { fetchAccessToken } from "./api.js"; export function getDevice(deviceId) { return fetchAccessToken() .then(accessToken => { return fetch(`https://your-api.com/devices/${deviceId}`, { headers: { "Authorization": `Bearer ${accessToken}` } }); }) .then(deviceResponse => { if (!deviceResponse.ok) throw new Error("Device fetch failed"); return deviceResponse.json(); }); } // Usage getDevice("device-123") .then(myDevice => console.log("Fetched device:", myDevice)) .catch(err => console.error("Error:", err));
Pro Tips to Improve This
- Cache the Token: If your token has an expiration date, store it in memory or
localStorageso you don’t re-fetch it every time. Check if it’s still valid before making a new auth request. - Centralize Auth Logic: Keep all token-related code in
api.jsso you don’t repeat it across other API functions. - Always Handle Errors: Async errors can be silent if you don’t catch them—make sure to use
try/catchor.catch()everywhere.
内容的提问来源于stack exchange,提问作者gregwinn

