【问题标题】:How to correctly turn closure to promise in amphp?如何在 amphp 中正确地将关闭转为承诺?
【发布时间】:2018-10-05 04:17:47
【问题描述】:

我正在学习 amphp。我想使用 amphp 中的事件循环将同步调用转换为异步调用。我的示例代码使用file_get_contents 作为示例阻塞调用。

使用同步调用,它看起来像这样:

$uris = [
    "https://google.com/",
    "https://github.com/",
    "https://stackoverflow.com/",
];

$results = [];
foreach ($uris as $uri) {
    var_dump("fetching $uri..");
    $results[$uri] = file_get_contents($uri);
    var_dump("done fetching $uri.");
}

foreach ($results as $uri => $result) {
    var_dump("uri : $uri");
    var_dump("result : " . strlen($result));
}

还有输出:

string(30) "fetching https://google.com/.."
string(34) "done fetching https://google.com/."
string(30) "fetching https://github.com/.."
string(34) "done fetching https://github.com/."
string(37) "fetching https://stackoverflow.com/.."
string(41) "done fetching https://stackoverflow.com/."
string(25) "uri : https://google.com/"
string(14) "result : 48092"
string(25) "uri : https://github.com/"
string(14) "result : 65749"
string(32) "uri : https://stackoverflow.com/"
string(15) "result : 260394"

我知道有 artax 可以异步调用。但是,我想学习如何正确地将阻塞代码转换为异步并发代码(非并行)。我已经成功地使用 amp 并行实现了它。

如果我在 amp 中成功实现异步,我相信正确的输出将是这样的:

string(30) "fetching https://google.com/.."
string(30) "fetching https://github.com/.."
string(37) "fetching https://stackoverflow.com/.."
string(34) "done fetching https://google.com/."
string(34) "done fetching https://github.com/."
string(41) "done fetching https://stackoverflow.com/."
string(25) "uri : https://google.com/"
string(14) "result : 48124"
string(25) "uri : https://github.com/"
string(14) "result : 65749"
string(32) "uri : https://stackoverflow.com/"
string(15) "result : 260107"

我已尝试使用此代码:

<?php
require __DIR__ . '/vendor/autoload.php';

use Amp\Loop;
use function Amp\call;

Loop::run(function () {
    $uris = [
        "https://google.com/",
        "https://github.com/",
        "https://stackoverflow.com/",
    ];

    foreach ($uris as $uri) {
        $promises[$uri] = call(function () use ($uri) {
            var_dump("fetching $uri..");
            $result = file_get_contents($uri);
            var_dump("done fetching $uri.");
            yield $result;
        });
    }

    $responses = yield $promises;

    foreach ($responses as $uri => $result) {
        var_dump("uri : $uri");
        var_dump("result : " . strlen($result));
    }
});

它给了我这个错误,而不是给我预期的结果:

string(30) "fetching https://google.com/.."
string(34) "done fetching https://google.com/."
string(30) "fetching https://github.com/.."
string(34) "done fetching https://github.com/."
string(37) "fetching https://stackoverflow.com/.."
string(41) "done fetching https://stackoverflow.com/."
PHP Fatal error:  Uncaught Amp\InvalidYieldError: Unexpected yield; Expected an instance of Amp\Promise or React\Promise\PromiseInterface or an array of such instances; string yielded at key 0 on line 20 

结果似乎也是同步运行的,而不是异步的。

我应该如何正确做呢?

【问题讨论】:

    标签: php amphp


    【解决方案1】:

    您需要使用您使用的函数的非阻塞实现。 file_get_contents 正在阻塞。您可以在 amphp/file 中找到非阻塞实现。如果将file_get_contents 替换为Amp\File\get,它应该可以正常工作。

    【讨论】:

      猜你喜欢
      • 2021-12-15
      • 2015-06-10
      • 1970-01-01
      • 2015-06-12
      • 2015-04-03
      • 2014-06-21
      • 2020-08-29
      相关资源
      最近更新 更多