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

如何在Koa+TypeScript中将回调数据传入ctx.body的data字段?

解决Koa路由中异步回调数据传递的问题

当然可以把回调里拿到的对象存入变量再放到ctx.body的data键里!不过你现在的代码里有个核心问题——request库的回调是异步执行的,你写的ctx.body = { data: body }会在回调函数触发之前就运行,所以根本拿不到回调里的body数据。

为什么会这样?

Node.js是异步非阻塞的,当你调用request(options, callback)时,这个函数会立刻返回,然后继续执行后面的ctx.body代码;而回调函数要等HTTP请求完成后才会触发。这就导致你设置ctx.body的时候,回调里的body还没被赋值,自然拿不到数据。

正确的解决方式:用Promise+await处理异步请求

Koa的路由支持async/await,所以最好的做法是把request的回调转换成Promise,这样就能用await等待请求完成,确保拿到数据后再设置ctx.body。

方案1:使用request-promise-native(推荐)

这是request库的Promise封装版本,直接支持await,用起来很方便。

首先安装依赖:

npm install request-promise-native @types/request-promise-native --save

然后修改你的路由代码:

import * as rp from 'request-promise-native';

router.post('/api/send_otp', async (ctx: Koa.Context, next: () => Promise<any>) => {
  const phone = ctx.request.body.phone;
  
  if (!phone) {
    ctx.body = { 
      message: "Please enter phone number" 
    };
    return; // 记得return,避免执行后面的代码
  }

  const options = {
    url: '', // 替换成你的实际请求URL
    method: 'POST',
    auth: {
      user: '', // 替换成实际用户名
      pass: ''  // 替换成实际密码
    },
    json: true, // 自动把返回的JSON解析成对象,无需手动JSON.parse
    resolveWithFullResponse: false // 只返回body,不需要整个response对象
  };

  try {
    // 用await等待请求完成,把结果存入变量
    const responseBody = await rp(options);
    console.log(responseBody); // 控制台依然能看到数据
    
    // 现在可以把变量传入ctx.body了
    ctx.body = { 
      data: responseBody 
    };
  } catch (error) {
    // 处理请求失败的情况
    console.log('error', error);
    ctx.body = { 
      message: "Failed to send OTP",
      error: error.message 
    };
    ctx.status = 500; // 设置合适的HTTP错误状态码
  }
});

方案2:手动封装Promise(无需额外依赖)

如果你不想安装新依赖,可以自己把request包装成Promise:

import * as request from 'request';

// 封装一个Promise版本的request工具函数
const requestPromise = (options: request.Options) => {
  return new Promise((resolve, reject) => {
    request(options, (error, response, body) => {
      if (error) {
        reject(error);
      } else if (response.statusCode !== 200) {
        // 可以根据状态码判断请求是否成功
        reject(new Error(`Request failed with status ${response.statusCode}`));
      } else {
        // 如果返回的是JSON字符串,手动解析成对象
        const parsedBody = typeof body === 'string' ? JSON.parse(body) : body;
        resolve(parsedBody);
      }
    });
  });
};

// 路由代码
router.post('/api/send_otp', async (ctx: Koa.Context, next: () => Promise<any>) => {
  const phone = ctx.request.body.phone;
  
  if (!phone) {
    ctx.body = { 
      message: "Please enter phone number" 
    };
    return;
  }

  const options = {
    url: '',
    method: 'POST',
    auth: {
      user: '',
      pass: ''
    }
  };

  try {
    const responseBody = await requestPromise(options);
    console.log(responseBody);
    ctx.body = { 
      data: responseBody 
    };
  } catch (error) {
    console.log('error', error);
    ctx.body = { 
      message: "Failed to send OTP",
      error: error.message 
    };
    ctx.status = 500;
  }
});

总结

完全可以把回调里的对象存入变量再传到ctx.body,但必须解决异步时序问题。用Promise+await的方式既符合Koa的异步编程风格,又能避免回调地狱,还能保证数据正确获取后再返回给客户端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 10:08:13