穿越地心之旅

(如果你了解洋葱圈模型,略过本小节)

首先让我们对洋葱圈模型有一个直观的认识:

地球构造

物理学上,地球可划分为岩石圈、软流层、地幔、外核和内核5层。

化学上,地球被划分为地壳、上地幔、下地幔、外核和内核。地质学上对地球各层的划分

演示Koa的中间件之前,我们用函数来描述一场穿越地心之旅:


  1. <?php
  2. function crust($next)
  3. {
  4. echo "到达<地壳>\n";
  5. $next();
  6. echo "离开<地壳>\n";
  7. }
  8. function upperMantle($next)
  9. {
  10. echo "到达<上地幔>\n";
  11. $next();
  12. echo "离开<上地幔>\n";
  13. }
  14. function mantle($next)
  15. {
  16. echo "到达<下地幔>\n";
  17. $next();
  18. echo "离开<下地幔>\n";
  19. }
  20. function outerCore($next)
  21. {
  22. echo "到达<外核>\n";
  23. $next();
  24. echo "离开<外核>\n";
  25. }
  26. function innerCore($next)
  27. {
  28. echo "到达<内核>\n";
  29. }
  30. // 我们逆序组合组合, 返回入口
  31. function makeTravel(...$layers)
  32. {
  33. $next = null;
  34. $i = count($layers);
  35. while ($i--) {
  36. $layer = $layers[$i];
  37. $next = function() use($layer, $next) {
  38. // 这里next指向穿越下一次的函数,作为参数传递给上一层调用
  39. $layer($next);
  40. };
  41. }
  42. return $next;
  43. }
  44. // 我们途径 crust -> upperMantle -> mantle -> outerCore -> innerCore 到达地心
  45. // 然后穿越另一半球 -> outerCore -> mantle -> upperMantle -> crust
  46. $travel = makeTravel("crust", "upperMantle", "mantle", "outerCore", "innerCore");
  47. $travel(); // output:
  48. /*
  49. 到达<地壳>
  50. 到达<上地幔>
  51. 到达<下地幔>
  52. 到达<外核>
  53. 到达<内核>
  54. 离开<外核>
  55. 离开<下地幔>
  56. 离开<上地幔>
  57. 离开<地壳>
  58. */

  1. <?php
  2. function outerCore1($next)
  3. {
  4. echo "到达<外核>\n";
  5. // 我们放弃内核,仅仅绕外壳一周,从另一侧返回地表
  6. // $next();
  7. echo "离开<外核>\n";
  8. }
  9. $travel = makeTravel("crust", "upperMantle", "mantle", "outerCore1", "innerCore");
  10. $travel(); // output:
  11. /*
  12. 到达<地壳>
  13. 到达<上地幔>
  14. 到达<下地幔>
  15. 到达<外核>
  16. 离开<外核>
  17. 离开<下地幔>
  18. 离开<上地幔>
  19. 离开<地壳>
  20. */

  1. <?php
  2. function innerCore1($next)
  3. {
  4. // 我们到达内核之前遭遇了岩浆,计划终止,等待救援
  5. throw new \Exception("岩浆");
  6. echo "到达<内核>\n";
  7. }
  8. $travel = makeTravel("crust", "upperMantle", "mantle", "outerCore", "innerCore1");
  9. $travel(); // output:
  10. /*
  11. 到达<地壳>
  12. 到达<上地幔>
  13. 到达<下地幔>
  14. 到达<外核>
  15. Fatal error: Uncaught exception 'Exception' with message '岩浆'
  16. */

  1. <?php
  2. function mantle1($next)
  3. {
  4. echo "到达<下地幔>\n";
  5. // 我们在下地幔的救援团队及时赶到 (try catch)
  6. try {
  7. $next();
  8. } catch (\Exception $ex) {
  9. echo "遇到", $ex->getMessage(), "\n";
  10. }
  11. // 我们仍旧没有去往内核,,绕道对端下地幔,返回地表
  12. echo "离开<下地幔>\n";
  13. }
  14. $travel = makeTravel("crust", "upperMantle", "mantle1", "outerCore", "innerCore1");
  15. $travel(); // output:
  16. /*
  17. 到达<地壳>
  18. 到达<上地幔>
  19. 到达<下地幔>
  20. 到达<外核>
  21. 遇到岩浆
  22. 离开<下地幔>
  23. 离开<上地幔>
  24. 离开<地壳>
  25. */

  1. <?php
  2. function upperMantle1($next)
  3. {
  4. // 我们放弃对去程上地幔的暂留
  5. // echo "到达<上地幔>\n";
  6. $next();
  7. // 只在返程时暂留
  8. echo "离开<上地幔>\n";
  9. }
  10. function outerCore2($next)
  11. {
  12. // 我们决定只在去程考察外核
  13. echo "到达<外核>\n";
  14. $next();
  15. // 因为温度过高,去程匆匆离开外壳
  16. // echo "离开<外核>\n";
  17. }
  18. $travel = makeTravel("crust", "upperMantle1", "mantle1", "outerCore2", "innerCore1");
  19. $travel(); // output:
  20. /*
  21. 到达<地壳>
  22. 到达<上地幔>
  23. 到达<下地幔>
  24. 到达<外核>
  25. 遇到岩浆
  26. 离开<下地幔>
  27. 离开<上地幔>
  28. 离开<地壳>
  29. */