node.js - 如何在 koa 中发送 HTTP 响应之前等待 url 回调?

标签 node.js asynchronous events synchronization koa

我有一个 koa 路由器,我需要调用一个 api,异步返回结果。这意味着我无法立即获得结果,api 会在正常时调用我的 callback url。但现在我必须像同步 api 一样使用它,这意味着我必须等到回调 url 被调用。

我的路由器是这样的:

router.post("/voice", async (ctx, next) => {
    // call a API here
    const params = {
        data: "xxx",
        callback_url: "http//myhost/ret_callback",
    };
    const req = new Request("http://xxx/api", {
        method: "POST",
        body: JSON.stringify(params),
    });
    const resp = await fetch(req);
    const data = await resp.json();

    // data here is not the result I want, this api just return a task id, this api will call my url back
    const taskid = data.taskid;

    // now I want to wait here until I got "ret_callback"

    // .... wait .... wait
    // "ret_callback" is called now
    // get the answer in "ret_callback"
    ctx.body = {
        result: "ret_callback result here",
    }
})

我的回调 url 是这样的:

router.post("/ret_callback", async (ctx, next) => {
    const params = ctx.request.body;

    // taskid will tell me this answer to which question
    const taskid = params.taskid;
    // this is exactly what I want
    const result = params.text;

    ctx.body = {
        code: 0,
        message: "success",
    };
})

那么我怎样才能让这个 aync api 像一个 sync api 一样呢?

最佳答案

只需将 resolve() 传递给另一个函数。例如,您可以这样做:

// use a map to save a lot of resolve()
const taskMap = new Map();

router.post("/voice", async (ctx, next) => {
    // call a API here
    const params = {
        data: "xxx",
        callback_url: "http//myhost/ret_callback",
    };
    const req = new Request("http://xxx/api", {
        method: "POST",
        body: JSON.stringify(params),
    });
    const resp = await fetch(req);
    const data = await resp.json();

    const result = await waitForCallback(data.taskid);

    ctx.body = {
        result,
    } })

const waitForCallback = (taskId) => {
    return new Promise((resolve, reject) => {
        const task = {};
        task.id = taskId;
        task.onComplete = (data) => {
            resolve(data);
        };
        task.onError = () => {
            reject();
        };
        taskMap.set(task.id, task);
    });
};

router.post("/ret_callback", async (ctx, next) => {
    const params = ctx.request.body;

    // taskid will tell me this answer to which question
    const taskid = params.taskid;
    // this is exactly what I want
    const result = params.text;

    // here you continue the waiting response
    taskMap.get(taskid).onComplete(result);
    // not forget to clean rubbish
    taskMap.delete(taskid);

    ctx.body = {
        code: 0,
        message: "success",
    }; })

我没有测试它,但我认为它会起作用。

关于node.js - 如何在 koa 中发送 HTTP 响应之前等待 url 回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50724912/

相关文章:

javascript - 使用 node.js 保存每 1 秒发送到 Postgres 的数据的最佳方法

javascript - 递增不起作用

node.js - 如何使用终端查找 Node-Sass 包中使用的 Sass 版本

javascript - 如何按日期时间优化数组过滤?

python - Requests 1.0.4 异步请求

c# - 在 Xamarin Forms 中的 PCL 同步方法中调用异步函数

events - 在 VBA 中运行宏之前检查工作表是否已更新

javascript - 使用 Node.js 监控 Mongo 的更改

c - 文件删除/修改期间的 libevent

c# - 在接口(interface)中实现委托(delegate)