You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法正确实现JavaScript中的异步XMLHttpRequest问题求助

Hey there! Let's break down why your async XMLHttpRequest logic isn't behaving as expected and fix it step by step.

The Core Problem

Your issue stems from the non-blocking nature of async operations: When you call makeRequest(myCallback), the browser fires off the XHR request but doesn't wait for it to finish. Instead, it immediately runs the rest of your code—console.log("print second") and return valueToBeReturned—before the API response even arrives. That's why valueToBeReturned stays at 0, and your callback never gets a chance to update it in time.


Solution 1: Fix Your Callback Implementation

Since you're already using callbacks, you need to refactor your code to handle the async result inside the callback (or pass the result to another callback), instead of trying to return it synchronously.

Here's the adjusted code:

// Let first_function accept a callback to pass the final result
function first_function(resultCallback) {
  makeRequest(function(responseData) {
    // Process the API response here
    const valueToBeReturned = responseData.targetValue; // Replace with your actual data extraction
    console.log("print second"); // This runs AFTER the request completes
    resultCallback(valueToBeReturned); // Pass the result to the callback
  });

  // This runs BEFORE the request finishes (async is non-blocking!)
  console.log("print first");
}

function makeRequest(callback) {
  var xhttp = new XMLHttpRequest();
  xhttp.open("GET", "my_url", true);
  
  xhttp.onload = function() {
    if(xhttp.readyState === 4) {
      if(xhttp.status === 200) {
        const response = JSON.parse(xhttp.responseText);
        callback(response); // Send the successful response to the callback
      } else {
        // Don't forget to handle error cases!
        callback(null, new Error(`Request failed: ${xhttp.status}`));
      }
    }
  };

  // Handle network errors too
  xhttp.onerror = function() {
    callback(null, new Error("Network error occurred"));
  };

  xhttp.send(null);
}

// How to use it:
first_function(function(result, error) {
  if(error) {
    console.error("Oops, something went wrong:", error);
    return;
  }
  console.log("Final result from API:", result);
});

Solution 2: Use Promises (Modern Approach)

Callbacks can get messy with nested logic, so Promises are a cleaner way to handle async operations. They let you chain logic and avoid "callback hell".

Refactored code with Promises:

function first_function() {
  // Return a Promise so the caller can handle the result later
  return makeRequest()
    .then(responseData => {
      const valueToBeReturned = responseData.targetValue;
      console.log("print second");
      return valueToBeReturned;
    })
    .catch(error => {
      console.error("Request failed:", error);
      throw error; // Pass the error up to the caller
    });

  console.log("print first"); // Runs before the request completes
}

function makeRequest() {
  return new Promise((resolve, reject) => {
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", "my_url", true);
    
    xhttp.onload = function() {
      if(xhttp.readyState === 4) {
        if(xhttp.status === 200) {
          const response = JSON.parse(xhttp.responseText);
          resolve(response); // Resolve the Promise with the response
        } else {
          reject(new Error(`Request failed: ${xhttp.status}`)); // Reject on HTTP errors
        }
      }
    };

    xhttp.onerror = function() {
      reject(new Error("Network error occurred")); // Reject on network issues
    };

    xhttp.send(null);
  });
}

// Usage option 1: .then()/.catch()
first_function()
  .then(result => console.log("Final result:", result))
  .catch(error => console.error(error));

// Usage option 2: async/await (even cleaner!)
async function useApiResult() {
  try {
    const result = await first_function();
    console.log("Final result:", result);
  } catch(error) {
    console.error(error);
  }
}
useApiResult();

Solution 3: Async/Await (Simplest Modern Syntax)

If your environment supports ES2017+ (most modern browsers and Node.js do), async/await lets you write async code that looks almost like synchronous code:

async function first_function() {
  try {
    // Wait for the request to complete before moving on
    const responseData = await makeRequest();
    const valueToBeReturned = responseData.targetValue;
    console.log("print second");
    return valueToBeReturned;
  } catch(error) {
    console.error("Request failed:", error);
    throw error;
  }
}

// makeRequest stays the same Promise-based function from Solution 2
function makeRequest() {
  return new Promise((resolve, reject) => {
    var xhttp = new XMLHttpRequest();
    xhttp.open("GET", "my_url", true);
    
    xhttp.onload = function() {
      if(xhttp.readyState === 4) {
        if(xhttp.status === 200) {
          const response = JSON.parse(xhttp.responseText);
          resolve(response);
        } else {
          reject(new Error(`Request failed: ${xhttp.status}`));
        }
      }
    };

    xhttp.onerror = function() {
      reject(new Error("Network error occurred"));
    };

    xhttp.send(null);
  });
}

// Usage
async function run() {
  console.log("print first");
  const result = await first_function();
  console.log("Final result:", result);
}
run();

Key Takeaway

You cannot return an async result synchronously—you have to use callbacks, Promises, or async/await to handle the logic that depends on the API response. Always remember to handle error cases too, so your code doesn't fail silently.

内容的提问来源于stack exchange,提问作者Tripti Rawat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:37:22