我要做的是:用户进行API调用,我给出响应,然后我开始执行耗时较长的操作,例如发送电子邮件。(电子邮件需要很长时间,因为我使用SMTP,所以swiftmailer是以同步的方式发送的。)
根据文档,finish()应该在发送响应后调用。然而,当我对此进行测试时,情况似乎并非如此。我的客户端一直在等待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等消息队列,我读到了关于它们的精彩内容。
下面接受的答案确实有效(也可以按照文档页面评论中的链接),但我发现解决方案对于我的特定情况来说不够干净。
我是不是误解了文件?
不,你没有。web响应的内容在finish
过滤器运行之前发送,但输出未刷新。尝试添加
ob_flush();
flush();
在sleep(5)
之前,它将如您所期望的那样工作。
您可能想要像SwiftmailerBundle那样伪造电子邮件。请参阅swiftmailer.use_spool.
默认情况下,Swiftmailer提供商使用KernelEvents::TERMINATE事件,在响应已发送。