我正在尝试做的是:用户进行API调用,我给出响应,然后我开始执行需要很长时间的操作,例如发送电子邮件。 (电子邮件需要很长时间,因为我使用的是SMTP,因此swiftmailer以同步方式执行此操作。)
根据documentation finish()应在响应发送后调用。然而,当我测试这个时,情况似乎并非如此。我的客户端一直等到完成()完成。
服务器端代码:
$app = new Silex\Application();
$app->get('/hello', function (Request $r) use($app) {
return $app->json("I should load within a few milliseconds.");
});
$app->finish(function() use () {
//Pretend to do some slow action afterwards
sleep(5);
});
$app->run();
现在,如果我加载页面http://localhost/hello
,则需要5秒才能加载。虽然我的期望是它会瞬间加载。我误解了文档吗?
技术上接受的答案符合我的要求。实际上我找到了一个不同的解决方案:
我一直在寻找一种方法来让我的电子邮件以最终用户不必等待的方式发送。出于我的目的,我切换到使用Swift_MailTransport
而不是Swift_SmtpTransport
,并将exim4本地配置为智能主机。通过这种方式,电子邮件将被移交给Exim4,并且脚本会立即继续。
如果您正在寻找其他长期流程而不仅仅是电子邮件,请查看消息队列,例如Beanstalk,我会阅读有关它们的精彩内容。
下面接受的答案确实有效(也请按照文档页面评论中的链接),但我发现解决方案不够干净,不适合我的特定情况。
答案 0 :(得分:1)
我误解了文档吗?
不,你没有。在运行finish
过滤器之前发送Web响应的内容,但输出不是flush。尝试添加
ob_flush();
flush();
在sleep(5)
之前,它会按照您的预期运作。
您可能需要spool之类的SwiftmailerBundle电子邮件。请参阅swiftmailer.use_spool。
默认情况下,Swiftmailer提供商使用。发送电子邮件 KernelEvents :: TERMINATE事件,在响应之后触发 已被发送。