javascript - 使用 PHP exec 调用 Node 脚本并在 finally 方法之前将数据返回给 PHP

标签 javascript php node.js es6-promise

我有一个 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/

相关文章:

php - 如何使用 php 对数组求和?

php - 使用用户缓存时 APC 崩溃

javascript - Access-Control-Allow-Origin 不允许 Origin <origin>

javascript - 尝试登录到express和node.js内置的身份验证系统时出现404错误(文件未找到)

javascript - JavaScript 中循环的奇怪行为

javascript - 将页面内容加载到一页(重复内容)对 SEO 不利?

Javascript:同步执行

javascript - 确定javascript函数中的调用div

php - 交响乐团 : Pagination with inner join

javascript - 两个机器人命令相互依赖