首页 > 解决方案 > 从闭包内部更新全局范围内的变量值

问题描述

我试图在我的数据库对象上并行执行一些过程(things),我使用这个包并行运行事物

https://github.com/spatie/async

我想知道我有多少事情已经成功处理,所以我$stats在全局范围内定义了数组并尝试从内部更新它

    $pool   = Pool::create();
    $things = Thing::all();

    $stats = [
        'total'   => count($things) ,
        'success' => [] ,
    ];

    foreach ($things as $thing) {

        $pool->add(function () use ($thing , $stats ) {

            // do stuff 
            return [$thing , $stats]  ;

        })->then(function ($output ) {

            // Handle success
            list( $thing  , $stats) = $output ;
            dump('SUCCESS');
            $stats['success'][$thing->id] = $thing->id ;


        }) ->catch(function ($exception){
            // Handle exception
            dump('[ERROR] -> ' . $exception->getMessage());
        });
    }

    $pool->wait();
    dump($stats);

即使我在输出中看到 SUCCESS 但是当我$stats在最后转储时我success总是为空

array:3 [▼
  "total" => 3
  "success" => []
]

我也试图stats通过then没有use 任何区别

})->then(function ($output ) use ($stats) 

$stats当我在里面转储时,then我可以看到数据工作正常

    })->then(function ($output ) {

        // Handle success
        list( $thing  , $stats) = $output ;
        dump('SUCCESS');
        $stats['success'][$thing->id] = $thing->id ;
        
        dump( $stats);


    })

内部转储的输出then

array:3 [▼
  "total" => 3
  "success" => array:1 [▼
    2 => 2
  ]
]

标签: phplaravelclosures

解决方案


你需要做几件事:

$stats通过引用从父范围继承,在第一个回调中使用以下内容:

use ($thing, &$stats)

然后返回相同的变量作为参考:

return [$thing, &$stats];

$output最后,在下一个回调中也通过引用取消引用相应的数组:

list($thing, &$stats) = $output;  // or [$thing, &$stats] = $output;

注意:这看起来有点粗略,我完全不确定这是使用这个库的正确方法,但这至少应该有效。


推荐阅读