微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

amphp 自动加载类没有按预期工作

如何解决amphp 自动加载类没有按预期工作

我正在尝试在使用 amPHP 的工作人员中使用自定义类,但它似乎不起作用。下面的类已经使用 Composer 自动加载。请帮我解决这个问题。我的代码如下:

Class(这实现了他们文档中提到的 Task):

<?PHP

namespace Jobs;

require '/home/xxx/vendor/autoload.PHP';

use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\Task;

class GetMarketJob implements Task {
    /**
     * @var callable
     */
    private $function;
    /**
     * @var mixed[]
     */
    private $args;

    public function __construct($function,...$args) {
        $this->function = $function;
        $this->args = $args;
    }

    /**
     * {@inheritdoc}
     */
    public function run(Environment $environment)
    {
        if ($this->function instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance as a callable,the class must be autoloadable');
        }

        if (\is_array($this->callable) && ($this->callable[0] ?? null) instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance method as a callable,the class must be autoloadable');
        }

        if (!\is_callable($this->function)) {
            $message = 'user-defined functions must be autoloadable (that is,defined in a file autoloaded by composer)';
            if (\is_string($this->function)) {
                $message .= \sprintf("; unable to load function '%s'",$this->function);
            }

            throw new \Error($message);
        }

        return ($this->function)(...$this->args);
    }

    public function testMe($url = NULL) {
        $test = file_get_contents($url);
        return $test;
    }    
}

文件使用 amPHP 使用上面的类分配工人:

    <?PHP

require '/home/xxxx/vendor/autoload.PHP';

use Jobs\GetMarketJob;
// Example async producer using promisor

use Amp\Parallel\Worker;
use Amp\Promise;
use Amp\Loop;
use Amp\Parallel\Worker\DefaultPool;
use Amp\Parallel\Worker\Task;
use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\TaskFailureError;
use Amp\Parallel\Worker\DefaultWorkerFactory;

Amp\Loop::run(function () {
    $factory = new DefaultWorkerFactory();

    $worker = $factory->create();

    $result = yield $worker->enqueue(new GetMarketJob('testMe',['https://www.syhtek.com']));
    
    print($result);

    $code = yield $worker->shutdown();
    \printf("Code: %d\n",$code);
});

运行这个脚本给了我以下输出

[2021 年 5 月 26 日 01:23:11 UTC] PHP 致命错误:未捕获 Amp\Parallel\Worker\TaskFailureError: 工人中未捕获的错误 消息“用户定义的函数必须是可自动加载的(即定义的 在作曲家自动加载的文件中);无法加载功能 'testMe'" 和代码“0”;采用 Amp\Parallel\Worker\TaskFailureError::getoriginalTrace() 用于堆栈 追踪工人 /home/xxxx/vendor/amPHP/parallel/lib/Worker/Internal/TaskFailure.PHP:60

非常感谢您的阅读!

解决方法

这里的问题是您传递了 'testMe',然后检查了 if (!\is_callable($this->function)) {,而它应该是 if (!\method_exists($this,$this->function)) {

如果您尝试调用该方法,则 return ($this->function)(...$this->args); 应该是 return ($this->{$this->function})(...$this->args);。您也可以直接调用该方法,而不是将其提供给构造函数。

如果你在 worker 中所做的一切都是一个 HTTP 请求,你应该查看 amphp/http-client 而不是 amphp/parallel,因为非阻塞 I/O 比几个具有阻塞 I/O 的 chlid 进程更有效/O。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。