我有一个 PHP 脚本,它使用 exec
函数来执行 Node 脚本并将一些数据返回到同一个 PHP 脚本。
我的问题是我需要将数据返回给 PHP,而不必等待 finally
中的清理代码完成。
我在下面编写了一些示例代码,向您展示代码的流程并说明我的问题。该代码示例未使用任何 Node 模块,但如果有帮助,请随意使用。
例子.php
$data = 'hello world';
$exec = 'node example.js ' . $data;
$escaped_command = escapeshellcmd($exec);
$data = exec($escaped_command);
// waits 10 seconds then displays returned data
// I need the code to return before finally executes
var_dump($data); // string(31) "Final data is final hello world"
例子.js
let data = process.argv[2];
// let data = "hello world";
async function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const doSomething = data => new Promise((resolve, reject) => {
if (data) {
resolve("new hello world");
} else {
reject();
}
});
const doSomethingElse = newData => new Promise((resolve, reject) => {
if (newData) {
resolve("final hello world");
} else {
reject();
}
});
(async() => {
try {
let newData = await doSomething(data);
let finalData = await doSomethingElse(newData);
// return this to server/php right now.
// Do not wait until finally script finishes
console.log("Final data is " + finalData);
} catch (err) {
// if error return this to server/php right now.
// Do not wait until finally script finishes
console.log(err);
} finally {
// does cleanup/closes node app
await timeout(10000);
}
})();
最佳答案
使用proc_open异步运行一个进程。让 Node 尽快输出数据。无需等待 Node 完成即可读取此数据:
// foo.js
process.stdout.write(JSON.stringify({"foo":"bar"})+"\n");
// simulate cleanup
setTimeout(() => {}, 3000);
// foo.php
<?php
$io = [
0 => ['pipe', 'r'], // node's stdin
1 => ['pipe', 'w'], // node's stdout
2 => ['pipe', 'w'], // node's stderr
];
$proc = proc_open('node foo.js', $io, $pipes);
$nodeStdout = $pipes[1]; // our end of node's stdout
echo date('H:i:s '), fgets($nodeStdout);
proc_close($proc);
echo date('H:i:s '), "done\n";
示例输出:
$ php foo.php
14:59:03 {"foo":"bar"}
14:59:06 done
proc_close 将等待 Node 进程退出,但您可以推迟等待,直到您完成 PHP 中的其他事情。
如果您不调用 proc_close,您可能会遇到僵尸进程,这取决于您的环境。 Docker and the PID 1 zombie reaping problem包含一个很好的解释。多指docker,因为这是僵尸多发的地方,但还是普遍适用的。
一些服务器 API 有为客户端“不可见地”运行代码的规定。例如,fcgi 有 fastcgi_finish_request ,您可以在 proc_close 之前调用它。这样 HTTP 客户端就不会注意到等待时间。
如果您不能容忍最终等待 Node ,请考虑将 Node 变成一个 Web 服务,它独立于 PHP 进行管理。
关于javascript - 使用 PHP exec 调用 Node 脚本并在 finally 方法之前将数据返回给 PHP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49756235/