php循环套循环_PHP中的事件循环简介
php循環套循環
PHP developers are always waiting for something. Sometimes we’re waiting for requests to remote services. Sometimes we’re waiting for databases to return rows from a complex query. Wouldn’t it be great if we could do other things during all that waiting?
PHP開發人員總是在等待某些東西。 有時我們正在等待對遠程服務的請求。 有時我們在等待數據庫從復雜的查詢返回行。 如果我們能在所有等待中做其他事情不是很好嗎?
If you’ve written some JS, you’re probably familiar with callbacks and DOM events. And though we have callbacks in PHP, they don’t work in quite the same way. That’s thanks to a feature called the event loop.
如果您已經編寫了一些JS,則可能熟悉回調和DOM事件。 盡管我們在PHP中有回調,但它們的工作方式并不完全相同。 這要歸功于稱為事件循環的功能。
We’re going to look at how the event loop works, and how we can use the event loop in PHP.
我們將研究事件循環如何工作,以及如何在PHP中使用事件循環。
We’re going to see some interesting PHP libraries. Some would consider these not yet stable enough to use in production. Some would consider the examples presented as “better to do in more mature languages”. There are good reasons to try these things. There are also good reasons to avoid these things in production. The purpose of this post is to highlight what’s possible in PHP.
我們將看到一些有趣PHP庫。 有些人會認為這些還不夠穩定,無法在生產中使用。 有些人會認為這些示例“更好地使用更成熟的語言”。 有充分的理由嘗試這些事情。 也有充分的理由避免在生產中使用這些方法。 這篇文章的目的是強調PHP中的功能。
等待的地方 (Where Things Go To Wait)
To understand event loops, let’s look at how they work in the browser. Take a look at this example:
要了解事件循環,讓我們看一下事件循環在瀏覽器中的工作方式。 看一下這個例子:
function fitToScreen(selector) {var element = document.querySelector(selector);var width = element.offsetWidth;var height = element.offsetHeight;var top = "-" + (height / 2) + "px";var left = "-" + (width / 2) + "px";var ratio = getRatio(width, height);setStyles(element, {"position": "absolute","left": "50%","top": "50%","margin": top + " 0 0 " + left,"transform": "scale(" + ratio + ", " + ratio + ")"}); }function getRatio(width, height) {return Math.min(document.body.offsetWidth / width,document.body.offsetHeight / height); }function setStyles(element, styles) {for (var key in styles) {if (element.style.hasOwnProperty(key)) {element.style[key] = styles[key];}} }fitToScreen(".welcome-screen");This code requires no extra libraries. It will work in any browser that supports CSS scale transformations. A recent version of Chrome should be all you need. Just make sure the CSS selector matches an element in your document.
此代碼不需要額外的庫。 它可以在任何支持CSS縮放轉換的瀏覽器中使用。 您需要的只是Chrome的最新版本。 只需確保CSS選擇器與文檔中的元素匹配即可。
These few functions take a CSS selector and center and scale the element to fit the screen. What would happen if we threw an Error inside that for loop? We’d see something like this…
這幾個功能采用CSS選擇器并居中并縮放元素以適合屏幕。 如果我們在該for循環中拋出Error ,將會發生什么? 我們會看到這樣的東西……
We call that list of functions a stack trace. It’s what things look like inside the stack browsers use. They’ll handle this code in steps…
我們將該函數列表稱為堆棧跟蹤。 這就是瀏覽器內部使用的堆棧外觀。 他們將逐步處理此代碼…
This is like how PHP uses a stack to store context. Browsers go a step further and provide WebAPIs for things like DOM events and Ajax callbacks. In its natural state, JavaScript is every bit as asynchronous as PHP. That is: while both look like they can do many things at once, they are single threaded. They can only do one thing at a time.
這就像PHP如何使用堆棧來存儲上下文。 瀏覽器更進一步,為諸如DOM事件和Ajax回調之類的事情提供WebAPI。 在自然狀態下,JavaScript與PHP一樣異步。 那就是:雖然看起來它們都可以一次完成很多事情,但是它們都是單線程的。 他們一次只能做一件事。
With the browser WebAPIs (things like setTimeout and addEventListener) we can offload parallel work to different threads. When those events happen, browsers add callbacks to a callback queue. When the stack is next empty, browses pick the callbacks up from the callback queue and execute them.
使用瀏覽器WebAPI(諸如setTimeout和addEventListener之類的東西),我們可以將并行工作卸載到不同的線程。 當這些事件發生時,瀏覽器會將回調添加到回調隊列中。 當堆棧下一個為空時,瀏覽器從回調隊列中選擇回調并執行它們。
This process of clearing the stack, and then the callback queue, is the event loop.
清除堆棧,然后清除回調隊列的過程是事件循環。
沒有事件循環的生活 (Life Without An Event Loop)
In JS, we can run the following code:
在JS中,我們可以運行以下代碼:
setTimeout(function() {console.log("inside the timeout"); }, 1);console.log("outside the timeout");When we run this code, we see outside the timeout and then inside the timeout in the console. The setTimeout function is part of the WebAPIs that browsers give us to work with. When 1 millisecond has passed, they add the callback to the callback queue.
運行此代碼時,我們會outside the timeout inside the timeout看到,然后inside the timeout控制臺中看到outside the timeout 。 setTimeout函數是瀏覽器提供給我們使用的WebAPI的一部分。 1毫秒過去后,他們將回調添加到回調隊列中。
The second console.log completes before the one from inside the setTimeout starts. We don’t have anything like setTimeout in standard PHP, but if we had to try and simulate it:
第二個console.log在setTimeout內部的一個console.log開始之前完成。 我們在標準PHP中沒有類似setTimeout東西,但是如果我們不得不嘗試對其進行仿真:
function setTimeout(callable $callback, $delay) {$now = microtime(true);while (true) {if (microtime(true) - $now > $delay) {$callback();return;}} }setTimeout(function() {print "inside the timeout"; }, 1);print "outside the timeout";When we run this, we see inside the timeout and then outside the timeout. That’s because we have to use an infinite loop inside our setTimeout function to execute the callback after a delay.
運行此命令時,我們會inside the timeout看到,然后outside the timeout 。 這是因為我們必須在setTimeout函數內使用無限循環才能在延遲后執行回調。
It may be tempting to move the while loop outside of setTimeout and wrap all our code in it. That might make our code feel less blocking, but at some point we’re always going to be blocked by that loop. At some point we’re going to see how we can’t do more than a single thing in a single thread at a time.
將while循環移到setTimeout外部并將所有代碼包裝在其中可能很誘人。 這可能會使我們的代碼減少阻塞,但是在某些時候,我們總是會被該循環阻塞。 在某個時候,我們將看到如何一次只能在單個線程中完成一件事情。
While there is nothing like setTimeout in standard PHP, there are some obscure ways to implement non-blocking code alongside event loops. We can use functions like stream_select to create non-blocking network IO. We can use C extensions like EIO to create non-blocking filesystem code. Let’s take a look at libraries built on these obscure methods…
盡管在標準PHP中沒有類似setTimeout東西,但是有一些晦澀的方法可以在事件循環旁邊實現非阻塞代碼。 我們可以使用類似stream_select功能來創建非阻塞網絡IO。 我們可以使用EIO之類的C擴展來創建非阻塞文件系統代碼。 讓我們看一下基于這些晦澀方法的庫…
冰柱 (Icicle)
Icicle is library of components built with the event loop in mind. Let’s look at a simple example:
冰柱是考慮到事件循環而構建的組件庫。 讓我們看一個簡單的例子:
use Icicle\Loop;Loop\timer(0.1, function() {print "inside timer"; });print "outside timer";Loop\run();This is with icicleio/icicle version 0.8.0.
這是icicleio/icicle版本0.8.0版本。
Icicle’s event loop implementation is great. It has many other impressive features; like A+ promises, socket, and server implementations.
冰柱的事件循環實現很棒。 它具有許多其他令人印象深刻的功能; 如A + promise,套接字和服務器實現。
Icicle also uses generators as co-routines. Generators and co-routines are a different topic, but the code they allow is beautiful:
冰柱還使用生成器作為協同例程。 生成器和協同例程是不同的主題,但是它們所允許的代碼很漂亮:
use Icicle\Coroutine; use Icicle\Dns\Resolver\Resolver; use Icicle\Loop;$coroutine = Coroutine\create(function ($query, $timeout = 1) {$resolver = new Resolver();$ips = (yield $resolver->resolve($query, ["timeout" => $timeout]));foreach ($ips as $ip) {print "ip: {$ip}\n";} }, "sitepoint.com");Loop\run();This is with icicleio/dns version 0.5.0.
這是icicleio/dns版本0.5.0 。
Generators make it easier to write asynchronous code in a way that resembles synchronous code. When combined with promises and an event loop, they lead to great non-blocking code like this!
生成器使它更容易以類似于同步代碼的方式編寫異步代碼。 當與promise和事件循環結合使用時,它們會導致像這樣的出色的非阻塞代碼!
ReactPHP (ReactPHP)
ReactPHP has a similar event loop implementation, but without all the interesting generator stuff:
ReactPHP具有類似的事件循環實現,但沒有所有有趣的生成器內容:
$loop = React\EventLoop\Factory::create();$loop->addTimer(0.1, function () {print "inside timer"; });print "outside timer";$loop->run();This is with react/event-loop version 0.4.1.
這是帶有react/event-loop版本0.4.1版本。
ReactPHP is more mature than Icicle, and it has a larger range of components. Icicle has a way to go before it can contend with all the functionality ReactPHP offers. The developers are making good progress, though!
ReactPHP比Icicle更成熟,并且具有更大范圍的組件。 冰柱要想與ReactPHP提供的所有功能抗衡,還有一段路要走。 不過,開發人員正在取得良好進展!
結論 (Conclusion)
It’s difficult to get out of the single-threaded mindset that we are taught to have. We just don’t know the limits of code we could write if we had access to non-blocking APIs and event loops.
很難擺脫我們被教導擁有的單線程思維方式。 如果我們可以訪問非阻塞API和事件循環,我們只是不知道可以編寫的代碼限制。
The PHP community needs to become aware of this kind of architecture. We need to learn and experiment with asynchronous and parallel execution. We need to pirate these concepts and best-practices from other languages who’ve had event loops for ages, until “how can I use the most system resources, efficiently?” is an easy question to answer with PHP.
PHP社區需要意識到這種架構。 我們需要學習和嘗試異步和并行執行。 我們需要從具有事件循環年齡的其他語言中盜用這些概念和最佳實踐,直到“我如何才能有效地利用最多的系統資源?” 用PHP回答一個簡單的問題。
Stay tuned for a more practical implementation of Icicle, coming soon!
請繼續關注Icicle的更實際實現,即將推出!
翻譯自: https://www.sitepoint.com/an-introduction-into-event-loops-in-php/
php循環套循環
總結
以上是生活随笔為你收集整理的php循环套循环_PHP中的事件循环简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Tableau-旭日图(详细操作步骤)
- 下一篇: 材料出租管理系统