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

如何使用Promise或async/await替代setTimeout实现Express接口等待异步请求完成

解决方法

核心思路是把原本回调风格的异步逻辑封装为Promise,就可以用async/await等待执行完成,完全替代不可靠的setTimeout方案。


第一步:改造makeCall函数

首先我们需要把异步请求、XML解析的回调逻辑都包装到Promise中,同时修复原代码中全局myRequest可能引发的并发请求冲突问题:

const { promisify } = require('util');
const parseString = promisify(require('xml2js').parseString);
// Node环境默认没有XMLHttpRequest,使用前需安装依赖:npm install xmlhttprequest
const { XMLHttpRequest } = require('xmlhttprequest');

const makeCall = async (call) => {
  return new Promise((resolve, reject) => {
    // 每次请求新建独立实例,不要用全局共享的myRequest,避免并发请求数据混乱
    const myRequest = new XMLHttpRequest();
    myRequest.open('POST', 'http://111.222.3.444:55555');
    myRequest.setRequestHeader('Content-Type', "application/x-www-form-urlencoded");
    myRequest.send(call);

    myRequest.onload = async () => {
      if (myRequest.status === 200) {
        try {
          const result = await parseString(myRequest.responseText);
          dataList.unshift(result);
          resolve(result); // 把解析完成的结果直接返回
        } catch (parseErr) {
          reject(parseErr);
        }
      } else {
        reject(new Error(`请求失败,状态码: ${myRequest.status}`));
      }
    };

    myRequest.onerror = () => reject(new Error('网络请求异常'));
  });
};

第二步:改造Express路由

将路由处理函数改为async函数,直接awaitmakeCall执行完成后再渲染页面:

app.get('/home', async (req, res) => {
  try {
    // 等待请求+XML解析完成后再继续执行,不需要硬等1秒
    await makeCall(`<root>
      <slipped>
        <mail>
          <alike>-1845676614.3625278</alike>
          <paid>uncle</paid>
          <kill>something</kill>
          <name>Stephen</name>
          <men>such</men>
          <firm>rubbed</firm>
          <using>yesterday</using>
        </mail>
      </slipped>
      <pour>-1247721160</pour>
      <poet>language</poet>
      <sets>-1907281866</sets>
      <treated>proper</treated>
      <judge>781679047</judge>
     </root>`);
    
    res.render('home.ejs', {
      name: dataList[0].root.slipped.mail.name
    });
  } catch (err) {
    // 统一捕获异常,避免请求无响应
    console.error(err);
    res.status(500).send('服务器处理失败');
  }
})

补充说明

  • 原方案的setTimeout属于固定延迟,不管请求什么时候完成都要等1秒,要是请求耗时超过1秒还是会拿到旧数据;优化后只要请求+解析完成就立即渲染,延迟更低也更可靠
  • 新增了错误捕获逻辑,请求失败、XML解析失败时服务不会直接崩溃,可以根据业务需求调整错误返回内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:15:01