如何等到回调被调用

Posted

技术标签:

【中文标题】如何等到回调被调用【英文标题】:How to wait until callback is called 【发布时间】:2019-05-22 20:59:59 【问题描述】:

我有一个执行长时间计算的函数,一旦完成,就会调用一个作为参数传递的回调函数。 我在 Koa 路由器中查询这个函数,需要将长时间计算的结果返回给浏览器。函数来自库,我无法更改其接口(即,我可以更改回调的代码,但无法更改 someLongComputation 以返回承诺)

当前代码集ctx.body 立即返回,someLongComputation 立即返回。知道,然后才使用回调的结果设置ctx.body

router.post(`/abc`, async (ctx) => 
  try 
      someLongComputation(function(err, res) 
          if(err) 
              console.log(err);
          
      
      ctx.body = 
        status: 'success',
        data: 'res' : "", 
        errors: []
      ;
   catch (err) 
      console.log(err)
  
)

【问题讨论】:

是的,您可以更改 someLongComputation() 以使用承诺:require('util').promisify(someLongComputation) 返回您可以使用 await 的函数版本。 为简单起见,我省略了 someLongComputation 函数的实际名称。我正在尝试使用在调整大小后运行的 graphicsmagic 流函数来做到这一点: gm(request(photo)).resize(size[0], size[1]).stream 。在该代码上使用 promisify 似乎会返回错误:TypeError: format.split is not a function 【参考方案1】:

你有两个选择。

1。从您的回调中发送响应

router.post(`/abc`, async (ctx) => 
  try 
    someLongComputation(function(err, res) 
      if (err) 
        console.log(err);
        // you might want to send error response here
      
      // send response from callback
      ctx.body = 
        status: 'success',
        data:  res: '' ,
        errors: []
      ;
    );
   catch (err) 
    console.log(err);
    // you might want to send error response here as well
  
);

2。从您的库函数中创建一个承诺并使用async/await

const doLongComputation = () => 
  return new Promise((resolve, reject) => 
    try 
      someLongComputation(function(err, res) 
        if (err) 
          console.log(err);
          reject(err);
        
        resolve(res);
      );
     catch (err) 
      console.log(err);
      reject(err);
    
  );
;

router.post(`/abc`, async (ctx) => 
  try 
    const res = await doLongComputation();
    ctx.body = 
      status: 'success',
      data:  res: '' ,
      errors: []
    ;
   catch (err) 
    console.log(err);
    // send error response here
  
);

【讨论】:

【参考方案2】:

如果您想使用 async/await 并假设 longcomputation 函数可以返回一个 Promise,您可以更改您的代码以等待该函数的返回。

router.post(`/abc`, async (ctx) => 
  try 
    const result = await someLongComputation();
    // do whatever you want with result

   catch (err) 
    console.log(err)
  
)

另一种选择是在函数的回调中使用变量

router.post(`/abc`, async (ctx) => 
  try 
    someLongComputation(function(err, res) 
      if(err) 
          console.log(err);
      
      //moved setting the body to inside the callback for the computation
      ctx.body = 
        status: 'success',
        data: 'res' : "", 
        errors: []
      ;
    
   catch (err) 
    console.log(err)
  
)

【讨论】:

谢谢彼得的回答。您的第一个解决方案将不起作用,因为我无法更改功能。我已经更新了我的问题以明确说明它的库函数。我刚刚测试了第二种解决方案,代码立即返回 404。 @user1217406 你是说你无法修改提供给someLongComputation()的匿名回调函数?总的来说,我很难弄清楚你认为什么是你可以修改的代码和你不能修改的代码 进一步编辑了问题。我可以更改回调,但我无法更改 someLongComputation 以使用承诺或以任何其他方式更改其接口。 如果您在回调中设置响应,我不确定为什么它会返回 404。另一个选项在下面的答案中。将您长期运行的函数包装在一个返回承诺然后等待该结果的函数中。我不知道引用另一个人的答案的礼仪是什么,但遵循@DaneshPandiyan 概述的答案应该会有所帮助

以上是关于如何等到回调被调用的主要内容,如果未能解决你的问题,请参考以下文章

如何等待未知调用者调用函数?

Jest 的回调测试实际上是如何工作的

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

简单理解函数回调——同步回调与异步回调

如何在koa发送HTTP响应之前等待url回调?

如何让函数调用等到另一个完成