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

为何JS函数无法为变量赋值?XMLHttpRequest异步问题排查

问题描述

我编写了一个获取用户兴趣的JS函数,调用后发现console.log(interest1)和return语句前的alert(customerInterest)都无法获取到值,但request.onload回调里的alert("---"+customerInterest)能正常显示预期结果。

我的JS函数代码

function interest(customerRef) {
   try { 
      var customerInterest = "";         
      var baseUrl="https://test/"
      var url = baseUrl+customerRef           
      var username = "username";
      var password = "password";

      var request = new XMLHttpRequest();
      request.open("GET", url);
      request.setRequestHeader("Authorization", "Basic " + btoa(username+":"+password))
      request.send()
      request.onload=()=>
      {               
           if(request.status==200)
           {                    
                var guestJson = JSON.parse(request.response);                
                var sessions = guestJson.sessions || [];               
                var interest = sessions.filter(session => session.events)
                     .flatMap(session => session.events)
                     .filter(event => event.type === "SEARCH")
                     .map(event => event.arbitraryData.interest)[0];     
                customerInterest = interest;   
                alert("---"+customerInterest);
           } 
           else
           {
                console.log(`error ${request.status} ${request.statusText}`)
           }
      }  
      alert(customerInterest);
      return customerInterest;
 }
 catch (error) {
      console.error(error);
 }     
 }

HTML调用代码

customerRef = "6a789727"          
var interest1 = "";
interest1 = interest(customerRef);
console.log(interest1);

问题原因

这是异步请求的执行顺序问题:
XMLHttpRequest.send()是异步操作,代码不会等待请求完成才继续执行后续逻辑。函数里的alert(customerInterest)和return customerInterest会在网络请求还未返回、onload回调尚未执行时就运行,此时customerInterest还是初始的空字符串。而onload回调要等请求成功返回后才会触发,这时候才会给customerInterest赋值,所以内部的alert能拿到正确值。


解决方案

方案1:用Promise封装函数(推荐)

将函数改为返回Promise,调用时通过async/await或then获取异步结果:

function interest(customerRef) {
  return new Promise((resolve, reject) => {
    try { 
      const baseUrl="https://test/"
      const url = baseUrl + customerRef           
      const username = "username";
      const password = "password";

      const request = new XMLHttpRequest();
      request.open("GET", url);
      request.setRequestHeader("Authorization", "Basic " + btoa(username+":"+password))
      request.send()
      
      request.onload = () => {               
        if(request.status === 200) {                    
          const guestJson = JSON.parse(request.response);                
          const sessions = guestJson.sessions || [];               
          const interest = sessions.filter(session => session.events)
               .flatMap(session => session.events)
               .filter(event => event.type === "SEARCH")
               .map(event => event.arbitraryData.interest)[0];     
          alert("---"+interest);
          resolve(interest); // 请求成功时返回结果
        } else {
          const errorMsg = `error ${request.status} ${request.statusText}`;
          console.log(errorMsg);
          reject(new Error(errorMsg)); // 请求失败时抛出错误
        }
      }

      request.onerror = () => {
        const errorMsg = "请求发生网络错误";
        console.error(errorMsg);
        reject(new Error(errorMsg));
      }
    } catch (error) {
      console.error(error);
      reject(error);
    }
  });
}

调用方式(async/await)

async function getCustomerInterest() {
  const customerRef = "6a789727"          
  const interest1 = await interest(customerRef);
  console.log(interest1);
}
getCustomerInterest();

调用方式(then回调)

const customerRef = "6a789727"          
interest(customerRef).then(interest1 => {
  console.log(interest1);
}).catch(error => {
  console.error(error);
});

方案2:使用回调函数

在函数参数中传入回调,请求完成后通过回调返回结果:

function interest(customerRef, callback) {
   try { 
      const baseUrl="https://test/"
      const url = baseUrl + customerRef           
      const username = "username";
      const password = "password";

      const request = new XMLHttpRequest();
      request.open("GET", url);
      request.setRequestHeader("Authorization", "Basic " + btoa(username+":"+password))
      request.send()
      
      request.onload = () => {               
        if(request.status === 200) {                    
          const guestJson = JSON.parse(request.response);                
          const sessions = guestJson.sessions || [];               
          const interest = sessions.filter(session => session.events)
               .flatMap(session => session.events)
               .filter(event => event.type === "SEARCH")
               .map(event => event.arbitraryData.interest)[0];     
          alert("---"+interest);
          callback(null, interest); // 成功时传入null和结果
        } else {
          const errorMsg = `error ${request.status} ${request.statusText}`;
          console.log(errorMsg);
          callback(new Error(errorMsg), null); // 失败时传入错误
        }
      }

      request.onerror = () => {
        const errorMsg = "请求发生网络错误";
        console.error(errorMsg);
        callback(new Error(errorMsg), null);
      }
   } catch (error) {
      console.error(error);
      callback(error, null);
   }     
 }

调用方式

const customerRef = "6a789727"          
interest(customerRef, (error, interest1) => {
  if (error) {
    console.error(error);
    return;
  }
  console.log(interest1);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 23:50:30