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

JavaScript异步请求中变量赋值时机错误致响应异常的解决

问题:异步操作导致数组未填充就返回响应的解决办法

我初始化了数组dataarr,需要把XML转JSON后的数据push进去,而且是在循环里收集数据。但我在异步操作的作用域外返回响应时,数组还没填充完整,一开始误以为是作用域问题,请问该怎么解决?

最小示例代码

{...
dataarr.push(jsonObj['soap:Envelope']['soap:Body']['ns:Response']['return']['items']);
} // scope 1 结束
res.status(200).send(dataarr); // 在scope 2中需向客户端返回响应

完整代码

let dataarr = [];

let payloadarr = [];
...
axios(config)
.then(function (response) {
 logger.log('info', 'POST /getdata successful from ' + req.ip);
 var options = {
   attributeNamePrefix : "@_",
   attrNodeName: "attr", //default is 'false'
   textNodeName : "#text",
   ignoreAttributes : true,
   ignoreNameSpace : false,
   allowBooleanAttributes : false,
   parseNodeValue : true,
   parseAttributeValue : false,
   trimValues: true,
   cdataTagName: "__cdata", //default is 'false'
   cdataPositionChar: "\\c",
   parseTrueNumberOnly: false,
   arrayMode: false, //"strict"
   attrValueProcessor: (val, attrName) => he.decode(val, {isAttributeValue: true}),//default is a=>a
   tagValueProcessor : (val, tagName) => he.decode(val), //default is a=>a
   stopNodes: ["parse-me-as-string"]
 };
 console.log("response.data:");
 console.log(response.data);
 if( parser.validate(response.data) === true) { //optional (it'll return an object in case it's not valid)
 var jsonObj = parser.parse(response.data,options);
}

var tObj = parser.getTraversalObj(response.data,options);
var jsonObj = parser.convertToJson(tObj,options);
console.log("jsonObj in parsing:");
console.log(jsonObj);
console.log(jsonObj['soap:Envelope']['soap:Body']['ns:getResponse']['return']['items']);
dataarr.push(jsonObj['soap:Envelope']['soap:Body']['ns:getResponse']['return']['items']);
console.log("dataarr getting filled:");
console.log(j);
console.log(dataarr);
})
.catch(function (error) {
  logger.warn('[/getdocumentmetadata]: ', new Error(error));
  //console.log(error);
});
}
})
.catch(function (error) {
  logger.warn('[GET /getdocuments]: ', new Error(error));
});
res.status(200).send(dataarr);
});
解决方案

这不是作用域问题,是异步操作的执行顺序导致的:axios请求是异步任务,代码会先执行到res.status(200).send(dataarr),此时then回调里的XML解析、数组填充逻辑还未执行,所以返回的是空数组。

解决方法一:将响应逻辑移到then回调内部

确保数据填充完成后再返回响应,直接把res.send放到then的末尾:

axios(config)
.then(function (response) {
  // ... XML转JSON、数据处理代码 ...
  dataarr.push(jsonObj['soap:Envelope']['soap:Body']['ns:getResponse']['return']['items']);
  // 数据准备完成后返回响应
  res.status(200).send(dataarr);
})
.catch(function (error) {
  logger.warn('[/getdocumentmetadata]: ', new Error(error));
  // 错误场景也要返回响应,避免客户端等待超时
  res.status(500).send({ error: '数据获取失败' });
});
// 删除外部的res.status(200).send(dataarr);

解决方法二:用async/await简化异步流程

将外层路由处理函数标记为async,用await等待axios请求完成,让代码按同步逻辑执行:

// 假设这是Express路由处理函数,添加async关键字
app.get('/your-api-path', async function(req, res) {
  let dataarr = [];
  let payloadarr = [];
  ...
  try {
    // 等待axios请求完成
    const response = await axios(config);
    logger.log('info', 'POST /getdata successful from ' + req.ip);
    // ... XML转JSON、数据处理代码 ...
    var jsonObj = parser.convertToJson(tObj, options);
    dataarr.push(jsonObj['soap:Envelope']['soap:Body']['ns:getResponse']['return']['items']);
    // 数据填充完成后返回响应
    res.status(200).send(dataarr);
  } catch(error) {
    logger.warn('[GET /getdocuments]: ', new Error(error));
    res.status(500).send({ error: '请求处理失败' });
  }
});

额外注意

如果是循环中多次调用axios,需要用Promise.all等待所有异步请求完成后再处理数组:

// 示例:循环生成多个axios请求Promise
const requestPromises = payloadarr.map(item => axios(getConfig(item)));
// 等待所有请求完成
const responses = await Promise.all(requestPromises);
// 遍历响应填充数组
responses.forEach(response => {
  const jsonObj = parser.convertToJson(parser.getTraversalObj(response.data, options), options);
  dataarr.push(jsonObj['soap:Envelope']['soap:Body']['ns:getResponse']['return']['items']);
});
// 最后返回响应
res.status(200).send(dataarr);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 22:05:58