如何在提前返回响应后保持代码运行



我需要将请求保存到数据库中,然后我必须调用API将数据同步到其他服务器。

我使用finally进行API调用,但PHP似乎仍在处理它,即使我在try子句中发送响应也是如此。

如何使其异步?我想尽可能快地发送响应,但在响应之后仍然处理API调用。

这就是简单代码的样子,描述我目前正在做的事情。

带有finally=>的代码;

public function store(Request $request)
{
try {
//returning the code early
return response("i am speed", 202);
} catch (Throwable $th) {
return response($th->getMessage(), 500);
} finally {
//lets says this is the super long too run
$i = 0;
$last = 11111111;
while ($i <= $last) {
$i++;
}
}
}
//this code finish in 1000ms

不带finally的代码=>

public function store(Request $request)
{
try {
return response("i am speed", 202);
} catch (Throwable $th) {
return response($th->getMessage(), 500);
}
} //this code finish in 90ms;

为什么会发生这种情况?

我已经发送了回复,但为什么不早点回复呢?

如何先发送响应,然后继续执行?

我已经解决了这个问题。正如评论所暗示的那样,Laravel有一个名为队列的功能,它将向数据库调度作业,在运行队列工作程序之前,这个过程不会运行。

要排队,我要做的是:

首先将.env QUEUE_CONNECTION更改为数据库。

QUEUE_CONNECTION=database

然后运行这个artisan命令来设置队列工作程序。

php artisan queue:table
php artisan migrate

之后,为要在队列中运行的函数创建一个作业。例如,我要把finally代码(问题中的那个(放在新工作中。

php artisan make:job exampleJobName

然后转到exampleJobName.php,在handle函数中编写将在队列中运行的代码。

public function handle()
{
//lets says this is the super long too run code
$i = 0;
$last = $this->data; //variable from constructor
while ($i <= $last) {
$i++;
}
} 
//exampleJobName.php

如果需要将变量传递给句柄,则在__construct函数中添加构造函数。

public function __construct($data)
{
$this->data = $data;
} 
//still inside the exampleJobName.php

然后一切都设置好了,转到想要运行这个作业的控制器(我要举一个问题中的例子(,并将代码更改为这个。

public function store(Request $request)
{
try {
$data = 111111111;
exampleJobName::dispatch($data);
//this will insert the job on the jobs table in the database
//therefore the job won't run until the queue worker is running

return response("i am speed", 202);
} catch (Throwable $th) {
return response($th->getMessage(), 500);
}
} 
//this code finish fast

一切都准备好了,然后只需在航站楼与手工服务并排运行队列工作人员。

php artisan queue:work

队列工作者将检查作业表中是否有任何作业尚未运行。然后将逐一运行。

我就是这么做的,希望这能帮助到别人。

感谢Tim Lewis在评论中向我展示了这个链接。

调用API将数据同步到其他服务器可能需要很长时间,因此我建议您为此创建并调度作业。

如果您仍然希望在发送响应后立即执行此操作,则可能需要使用dispatchAfterResponse。

最新更新