• PHP yield


    概念:

            Generator:带 yield的function

            yield:Generator或task的中断关键字,执行到yield时一次调度周期执行完即阻塞,并返回右侧表达式结果,等待下一次调度器运行next()或迭代遍历才会继续往下执行,直至Generator所有迭代或yield语句全部执行完毕

            valid():返回bool值,表示Generator是否未完成,即是否有yield等待执行,(若是Generator创建之后第一次执行此方法,则会从Generator内开始处到第一次yield出现的地方,相当于rewind() 一次)

            current():返回Generator当前值,即yield右侧表达式的值,并且会 执行 上一次yield到本次yield之间的部分(若是Generator创建之后第一次执行此方法,则会从Generator内开始处到第一次yield出现的地方,相当于rewind() 一次)

            rewind():重置Generator状态回到最开始状态,即第一个yield 执行前

            next():执行一次yield之后的代码直到下一次yield停止,yield 下边的代码不会执行 (若是Generator创建之后第一次执行此方法,则会从Generator内开始处到第一次yield出现的地方,相当于rewind() 一次,然后再往第一个yield下面继续执行一次,直到遇到第二个yield停止)

            yield from:后边跟普通数组,或者跟一个Generator 组成嵌套生成器结构,不希望去手动调用Generator的current(),那么在Generator前 使用 yield from 交给上游(框架)来解决。

            send(data):发送data到generator内部,generator接受数据data后,完成 yield->data的替换,并继续从当前中断的yield处往下再执行一次迭代,直到遇到下一次yield(当前执行的是generator的最后一次yield时,会直接完成generator所有迭代,此时valid()返回false)

    1. function A(){
    2. echo 'In A before of loop'.PHP_EOL;
    3. for($i=0;$i<2;$i++){
    4. echo 'In A in loop up'.PHP_EOL;
    5. yield;
    6. echo 'In A in loop down'.PHP_EOL;
    7. }
    8. echo 'In A after of loop'.PHP_EOL;
    9. }
    10. $a = A();
    11. // var_dump($a->valid());
    12. // var_dump($a->current());
    13. $a->next();
    14. // $a->next();
    15. // var_dump($a->current());
    16. // $a->valid();
    17. // $a->valid();
    18. // $i = 0;
    19. // while(true){
    20. // if($a->valid()){
    21. // $i++;
    22. // echo '第 '.$i.' 次执行next()';
    23. // $a->next();
    24. // }else{
    25. // break;
    26. // }
    27. // }
    28. echo PHP_EOL.'All done'.PHP_EOL;

            yield from:后面跟一个数组,创建一个临时Generator实例,每次迭代时依次返回数组的每个元素

    1. //yield from
    2. function test()
    3. {
    4. yield from [1, 3, 5, 7];
    5. }
    6. $a = test();
    7. var_dump($a->current());
    8. $a->next();
    9. var_dump($a->current());

    //通过使用php yield + 异步非阻塞select()单线程发送多个socket请求并统一获取返回结果,大佬写的示例代码:

    PHP Generator Yield Demo: PHP 生成器 yield 语法Demo

    //异步非阻塞,yield实现的事件循环统一监听多个socket请求状态的例子:

    小白要生发icon-default.png?t=N7T8https://segmentfault.com/a/1190000022979052

    yield事件监听实现 promise::All()的意义:

    1. 用同步的代码,发起异步请求,多个请求可并发,从IO串行等待,改为并行等待,减少无畏的等待时间。提高业务程序的效率同时,不降低代码可读性。
    2. 在一个线程内通过事件循环,尽可能处理多个请求,缓解了一个请求一个线程带来的频繁线程切换,从核心上提高运行效率。

    promise::All() 核心代码:

    1. /**
    2. * all()返回的是一个generator,外面的事件循环监听到任意一个 promise状态变更都会调用此
    3. * generator的send()方法,从事件监听到的数据传入到此generator内部
    4. */
    5. public static function all(...$promises)
    6. {
    7. $re = array();
    8. foreach ($promises as $promise)
    9. {
    10. //此处yield将会被send()传递的数据代替,作为promise状态结构收集数组中的一员保存起来,
    11. //当所有promise的结构都是完成状态后,此循环中的所有yield即迭代完成,即完成异步多个事件的结果收集,返回结果
    12. $re[] = yield;
    13. }
    14. /**
    15. * @var Promise $promise
    16. */
    17. $promise = null;
    18. foreach ($promises as $promise) {
    19. foreach ($re as $param) {
    20. //由于promise的收集结果不是按原始顺序排列,而是谁先收到数据谁向结果中写入,此
    21. //处需要使用特殊标记 streamName 来作promise和对应结果的匹配和关联,并返回给外
    22. //部一个最终结果
    23. if ($param['streamName'] == $promise->getStreamName()) {
    24. $results[] = $param['data'];
    25. }
    26. }
    27. }
    28. return $results;
    29. }

  • 相关阅读:
    CUDA编程- __syncthreads()函数
    【开源】SpringBoot框架开发陕西非物质文化遗产网站
    点与多边形关系
    什么是DeFi流动性资金池
    分享从零开始学习网络设备配置(华为ensp版本)------任务1.1 安装eNSP模拟器
    什么是JavaScript中的严格模式(strict mode)?应用场景是什么?
    day14 - 提取图像信息
    跨网段主机搭建k8s集群注意事项
    如何获取QColorDialog.getColor()的取消事件
    【Hadoop】- MapReduce & YARN 初体验[9]
  • 原文地址:https://blog.csdn.net/MyLoveSunset7777/article/details/133920384