当前位置: 首页 > news >正文

龙岗网站建设价位哈尔滨设计网站建设

龙岗网站建设价位,哈尔滨设计网站建设,建设银行重置网站查询密码,佛山专业英文网站建设摘要: 我们知道 JavaScript 自从有了 Generator 之后#xff0c;就有了各种基于 Generator 封装的协程。其中 hprose 中封装的 Promise 和协程库实现了跟 ES2016 的 async/await 一样的功能#xff0c;并且更加灵活。我们还知道 PHP 自从 5.5 之后#xff0c;也引入了 Gener…摘要: 我们知道 JavaScript 自从有了 Generator 之后就有了各种基于 Generator 封装的协程。其中 hprose 中封装的 Promise 和协程库实现了跟 ES2016 的 async/await 一样的功能并且更加灵活。我们还知道 PHP 自从 5.5 之后也引入了 Generator同样也有了各种基于它封装的 PHP 协程库hprose 同样也为 PHP 提供的跟 JavaScript 版本类似的 Promise 和协程库。下面我们就来看一下它跟 swoole 结合的效果。为什么需要异步方式一个函数执行之后在它后面顺序编写的代码中如果能够直接使用它的返回结果或者它修改之后的引用参数那么我们通常认为该函数是同步的。而如果一个函数的执行结果或者其修改的引用参数需要通过设置回调函数或者回调事件的方式来获取而在其后顺序编写的代码中无法直接获取的话那么我们通常认为这样的函数是异步的。PHP 提供的大部分函数都是同步的。通常我们会有一个误解那就是容易把同步和阻塞当成同一个概念但实际上同步代码不一定都是阻塞的只是同步代码对阻塞天然友好当同步代码和阻塞结合时代码通常是简单易懂的。阻塞带来的问题是当前线程(或进程)会陷入等待一直等到阻塞结束这样就会造成线程(或进程)资源的浪费。所以通常认为阻塞是不够高效的。但是如果要编写非阻塞代码使用同步方式会变得有些复杂且不够灵活。同步方式的非阻塞代码通常会使用 select 模式例如 curl_multi_select, stream_select, socket_select 等就是 PHP 中提供的一些典型的 select 模式的函数。我们说它复杂且不够灵活是有理由的例如使用上面的 select 模式编写同步的非阻塞代码时我们需要先构造一个并发任务的列表之后手动构造循环来执行这些并发的任务在循环开始之后虽然这几个任务可以并发但是这个循环相对于其后的代码总体上仍然是阻塞的我们要想拿到这些并发任务的结果时仍然需要等待。select 虽然可以同时等待多个任务中某一个或几个就位后再执行后续操作但仍然有一部分时间是被等待消耗掉的。而且如果是纯同步非阻塞的情况下我们也很难在循环开始后动态添加更多的任务到这个循环中去。所以如果我们希望程序能够更加高效更加灵活就需要引入异步方式。传统的异步方式有什么问题一提到异步模式大家脑子中的第一印象可能就是回调、回调、回调。是的这是最简单最直接也是之前最常见的异步模式。只要在调用异步函数时设置一个或多个回调函数函数就会在完成时自动调用回调函数。或者为一个对象设置一堆事件之后调用该对象上的某个异步方法虽然这个异步方法本身可能不再需要设置回调函数但是设置的这堆事件实际上跟回调函数所起到的作用是一样的。如果你的程序逻辑够简单简单的一两层回调也许并不会让你觉得异步方式的编程有什么麻烦。但如果你的程序逻辑一旦有些复杂你可能就会被层层回调搞得疲惫不堪了。当然实际上你的程序需要层层回调的原因也许并不是你的程序逻辑真的复杂而是你没有办法将回调函数中的参数结果传出来所以你就不得不将另一个回调函数传进去。我们来举一个简单的例子假设我们有 1 个同步函数function sum($a, $b) {return $a $b;}然后我们按照下面的方式去调用它$a sum(1, 2);$b sum($a, 3);$c sum($b, 4);var_dump(array($a, $b, $c));虽然上面的代码很不精简但我们要表达的意图很明确而且代码看起来很清楚。那接下来我们把这个函数换成一个形式上的异步函数例如function async_sum($a, $b, $callback) {$callback($a $b);}当然它的执行并不是异步的这里我们先不关心它的实现是不是真异步的。现在如果要做上面同样的操作代码就要这样写了async_sum(1, 2, function($a) {async_sum($a, 3, function($b) use ($a) {async_sum($b, 4, function($c) use ($a, $b) {var_dump(array($a, $b, $c));});});});代码的执行结果是一样的。但异步的代码看起来显然更难读一些虽然这已经是很简单的例子了。好了看到这里有些读者可能会觉的我上面的这个例子很糟糕。因为明明有同步的函数可以使用并且代码清晰可读为啥非要写个形似异步的函数把本来同步可以做的很好的事情用异步方式复杂化呢而且那个异步调用的方式最后不还是想要实现同步化的结果吗如果你这么想的话一点都没错。但我们这里想要解决的问题是如果我们拿到的只有一个异步函数这个函数没有同步实现我们也不知道这个异步函数的内部定义是怎样的我们也没办法将这个异步函数改为同步函数实现。那我们有没有办法将上面的程序改的更可读一些呢当然是可以的所以现在 Promise 要登场了。为什么要引入 Promise通常我们对 Promise 的一个误解就是它要解决的是层层回调的问题比如上面的问题看上去就是一个典型的层层回调的问题。然而实际上Promise 要解决的并不是回调不回调的问题如果你使用过 Promise 的话你会发现使用 Promise 你仍然少不了要使用回调。Promise 要解决的问题是如何将回调方法的参数从回调方法中传递出来让它可以像同步函数的返回结果一样在回调函数以外的控制范围内可以传递和复用。下面这几篇文章可能会对大家理解 Promise 有所帮助我觉得这几篇文章讲的比较透彻所以我就不重复文章中的内容了。下面我们来看上面的例子用 Promise 如何解。我们现在用最简单粗暴的方式来引入 Hprose 的库直接复制源码而不是使用 composer。然后我们在代码中直接使用require_once(Hprose.php);use Hprose\Promise;这种方式来引入 Hprose 的 Promise 库当然你也可以写成require_once(Hprose.php);use Hprose\Future;Future 库跟 Promise 库基本上是一样的你可以认为 Future 是 Promise 的具体实现Promise 只是 Future 实现的一个包装。这个区别你可以从源码中直接看出来这里就不多做解释了。接下来我们要把前面的 async_sum 函数 Promise 化Hprose 提供了这样一个函数Promisepromisify(或者 Futurepromisify)它的作用就是将一个使用回调方式的异步函数变成一个返回 Promise 对象的异步函数。这样说也许有些不好理解下面直接上代码require_once(Hprose.php);use Hprose\Promise;function async_sum($a, $b, $callback) {$callback($a $b);}$sum Promise\promisify(async_sum);$a $sum(1, 2);$b $a-then(function($a) use ($sum) {return $sum($a, 3);});$c $b-then(function($b) use ($sum) {return $sum($b, 4);});Promise\all(array($a, $b, $c))-then(function($result) {var_dump($result);});好了看到这里如果你对 Promise 的理解还不够深入的话你的第一反应可能是这不是把程序变得更复杂了吗原来的程序是 3 个回调现在仍然是 3 个回调还多了包装都玩出花来了有意思吗确实从上面的代码来看代码并没有被简化但是你会发现现在回调函数中的参数已经通过 Promise 返回值的方式传递出来了而且可以在原本的回调函数控制范围以外被传递和复用了。但是你可能会说然并卵程序不是仍然很复杂吗那我们就来进一步简化一下require_once(Hprose.php);use Hprose\Promise;function async_sum($a, $b, $callback) {$callback($a $b);}$sum Promise\wrap(Promise\promisify(async_sum));$var_dump Promise\wrap(var_dump);$a $sum(1, 2);$b $sum($a, 3);$c $sum($b, 4);$var_dump(Promise\all(array($a, $b, $c)));现在代码中再也看不到回调了。因为我们把函数包装成了可以接收 Promise 变量的函数。当然其实现细节略微有些复杂如果你感兴趣可以去看一下源码这里就不做源码剖析了。如果感兴趣的读者多得话以后有时间再写源码剖析。当然如果你只是想把异步调用同步化除了 Promisewrap 外你还可以通过 co/yield 协程来实现。Hprose 中的 co/yield 协程还是上面的例子如果你使用的是 PHP 5.5 或者更高版本那么你可以这样来写代码了。require_once(Hprose.php);use Hprose\Promise;function async_sum($a, $b, $callback) {$callback($a $b);}Promise\co(function() {$sum Promise\promisify(async_sum);$a (yield $sum(1, 2));$b (yield $sum($a, 3));$c (yield $sum($b, 4));var_dump(array($a, $b, $c));});这代码比使用 Promisewrap 的又要简单了。这里代码中的变量 $a, $b, $c 不再是 Promise 变量而是实实在在的整数变量。也就是说yield 把一个 Promise 变量变成了一个普通变量。现在 Promiseco 中的代码已经被实实在在的同步化了。现在你可能有新的疑问了异步不是为了高效吗现在把原本的异步代码同步化了那还会高效吗当然对这个例子上来说效率肯定是没有提高反而是严重降低的。甚至在这个例子中最原始的那个形似异步的实现也不比同步实现更高效。因为在这个例子中并没有涉及到并发和 IO 阻塞的情况。下面我们就放到真实场景下来看看 Promise 和 co/yield 协程是怎么用的。在 swoole 下使用 Promise 和 co/yield 协程我们知道在 PHP 中如果要让程序延时可以使用 sleep 函数(或者 usleep, time_nanosleep 函数)来让程序阻塞一会儿但是这个阻塞会让整个进程都阻塞所以在阻塞期间什么都不能干。下面我们来看看使用 swoole_timer_after 实现的延时执行require_once(Hprose.php);use Hprose\Future;date_default_timezone_set(UTC);function wait($time) {$wait Future\promisify(swoole_timer_after);for ($i 0; $i 5; $i) {yield $wait($time);var_dump(wait . ($time / 1000) . s, now is . date(H:i:s));}}Future\co(wait(2000));Future\co(wait(1000));该程序执行结果如下string(24) wait 1s, now is 13:48:25string(24) wait 2s, now is 13:48:26string(24) wait 1s, now is 13:48:26string(24) wait 1s, now is 13:48:27string(24) wait 2s, now is 13:48:28string(24) wait 1s, now is 13:48:28string(24) wait 1s, now is 13:48:29string(24) wait 2s, now is 13:48:30string(24) wait 2s, now is 13:48:32string(24) wait 2s, now is 13:48:34从结果中我们可以看出wait(2000) 和 wait(1000) 各自都是顺序阻塞执行的但是它们之间却是并发执行的。也就是说协程之间并不会相互阻塞虽然这几个并发的协程是在同一个进程内跑的。最后我们再来看一个用 co/yield 协程实现的并发抓图程序require_once(Hprose.php);use Hprose\Promise;function fetch($url) {$dns_lookup Promise\promisify(swoole_async_dns_lookup);$writefile Promise\promisify(swoole_async_writefile);$url parse_url($url);list($host, $ip) (yield $dns_lookup($url[host]));$cli new swoole_http_client($ip, isset($url[port]) ? $url[port] : 80);$cli-setHeaders([Host $host,User-Agent Chrome/49.0.2587.3,]);$get Promise\promisify([$cli, get]);yield $get($url[path]);list($filename) (yield $writefile(basename($url[path]), $cli-body));echo write $filename ok.\r\n;$cli-close();}$urls array(http://b.hiphotos.baidu.com/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign5f4519ba037b020818c437b303b099b6/472309f790529822434d08dcdeca7bcb0a46d4b6.jpg,http://f.hiphotos.baidu.com/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/sign1c37718b3cc79f3d9becec62dbc8a674/38dbb6fd5266d016dc2eaa5c902bd40735fa358a.jpg,http://h.hiphotos.baidu.com/baike/c0%3Dbaike116%2C5%2C5%2C116%2C38/signedd05c9c502c11dfcadcb771024e09b5/d6ca7bcb0a46f21f3100c52cf1246b600c33ae9d.jpg,http://a.hiphotos.baidu.com/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign4693756e8094a4c21e2eef796f9d70b0/54fbb2fb43166d22df5181f5412309f79052d2a9.jpg,http://a.hiphotos.baidu.com/baike/c0%3Dbaike92%2C5%2C5%2C92%2C30/sign9388507144a98226accc2375ebebd264/faf2b2119313b07eb2cc820c0bd7912397dd8c45.jpg,);foreach ($urls as $url) {Promise\co(fetch($url));}在这个程序中fetch 函数内的代码是同步执行的但是多个 fetch 之间却是并发执行的从结果输出就可以看出来输出顺序是不一定的。但最后你总能得到所有的美图。总结通过 swoole 跟 hprose 中的 Promise 和 co/yield 协程相结合你可以方便的使用同步的方式来调用 swoole 中的异步函数和方法并可以实现协程间的并发。因为篇幅所限这里无法把 hprose 中 Promise 和 co/yield 协程的全部内容都介绍完如果你想了解更多可以参考下面两篇内容
http://www.huolong8.cn/news/293906/

相关文章:

  • 网站二级分类深圳58同城招聘网
  • php企业网站网页开发者工具
  • 网站建设的利弊wordpress cms列表
  • c2c网站建设策划书火车头 wordpress 4.9
  • 网站可以换域名吗百度云wordpress建站
  • 网页设计的交流网站网站后台扫描插件
  • 巴零网站建设wordpress小说网站模板下载地址
  • 黄冈网站优化公司哪家好wordpress ftp备份
  • 国家示范院校建设网站h5 高端网站建设
  • 现在哪个行业做网站需求多点浙江网站建设制作流程
  • 优秀校园网站网络编程培训
  • wordpress网站如何提速乌兰浩特网站开发
  • 贾汪徐州网站开发学网页设计学徒培训
  • 山东信达建设有限公司网站国内的优秀网站
  • 福田网站建设公司北京王府井攻略
  • 网站建设公司的市场开发方案项目融资平台
  • 怎么知道网站是哪个公司做的打开网站自动跳转代码
  • 广州市网站建设制作做高大上分析的网站
  • 赤峰最好的网站建设公司静态网页模板免费下载的网站
  • 网站建设开发公司推荐指数一流的郑州网站建设
  • 做网站网页的专业昌邑做网站的公司
  • 网站平台搭建怎么弄的215做网站
  • 广东网站备案电话号码网站底部版权代码
  • 微信营销推广软件网站建设 seo
  • 网站开发毕设dw6做网站
  • 建设网站的初步需要so域名的网站有哪些
  • 广州网站设计公司推荐哪家网站排名 影响因素
  • 手机网站建设软件网站海外推广方案
  • 天津 网站优化天津建设银行东丽网站
  • typecho做网站自助建站门户网站