4-1 异步编程的处理
本节编程练习不计算学习进度,请电脑登录imooc.com操作

异步编程的处理

JavaScript的执行流程是分为"同步"与"异步"

传统的异步操作会在操作完成之后,使用回调函数传回结果,而回调函数中则包含了后续的工作。这也是造成异步编程困难的主要原因:

我们一直习惯于“线性”地编写代码逻辑,但是大量异步操作所带来的回调函数,会把我们的算法分解地支离破碎。

嵌套式回调

动画为例,下一个动画要等上一个执行完毕才可以继续,流程就会写到回调里面

//执行多个动画
$('ele1').animate({
    opacity: '.5'
}, 4000, function() {
    $('ele2').animate({
        width: '100px'
    }, 2000, function() {
        $('ele3').animate({
            height: '0'
        }, 2000);
    });
});

上面的代码编程逻辑也是正确的,但是针对这样的异步嵌套的回调逻辑,当我们的嵌套越多,代码结构层级会变得越来越深。首先是阅读上会变得困难,其次是强耦合,接口变得不好扩展。我们需要一种模式来解决这种问题,这就是Promises所要做的事情。

为了让前端们从回调的地狱中回到天堂, jQuery 也引入了 Promise 的概念。 Promise 是一种令代码异步行为更加优雅的抽象,有了它,我们就可以像写同步代码一样去写异步代码。这个东东看起来很复杂,实际上我们只要抓住核心的使用就可以了

观察右边代码:

通过$.Deferred处理过的代码,很明显没有了回调的嵌套,虽然代码量看起来多了点,但是实际上,每一个代码执行部分都被封装了起来,只留了Deferred的接口处理了,等于是我们把执行的流程控制交给了Deferred,这样的好处就是我们在写嵌套函数的时候,可以用deferred提供的管道风格编写同步代码了

dtd.then(function() {
   //操作1
}).then(function() {
   //操作2
}).then(function() {
  //操作3
})

这里要了解3个步骤

var dtd = $.Deferred();  //创建
dtd.resolve();          //成功
dtd.then()              //执行回调

具体的我们可以参考下jQuery的Deferred部分的API说明,点击此处

我们将会在下一节,用jQuery的Deferred去改造代码的执行流程

任务

  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
  6. <title>慕课七夕主题</title>
  7. <style type="text/css">
  8. div {
  9. background-color: yellow;
  10. width: 200px;
  11. height: 200px;
  12. text-align: center;
  13. border: 2px solid red;
  14. margin: 3px;
  15. font-size: 14px;
  16. }
  17. #block3,#block4{
  18. background-color: #CAE1FF;
  19. }
  20. button {
  21. font-size: 14px;
  22. }
  23. </style>
  24. <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script>
  25. </head>
  26.  
  27. <body>
  28. <button>点击测试回调处理</button>
  29. <button>点击测试$.Deferred处理</button>
  30. </br>
  31. </br>
  32. <div id="block1">block1执行动画</div>
  33. <div id="block2">block2执行动画</div>
  34. <div id="block3">block3执行动画</div>
  35. <div id="block4">block4执行动画</div>
  36.  
  37. <script type="text/javascript">
  38. // 回调处理
  39. $('button:first').click(function() {
  40. $("#block1").animate({
  41. width: "50%"
  42. }, 2000, function() { // 嵌套回调
  43. $("#block2").animate({
  44. width: "50%"
  45. }, 2000);
  46. });
  47. });
  48.  
  49. // jQuery的Deferred处理
  50. $('button:last').click(function() {
  51.  
  52. function animate1() {
  53. var dtd = $.Deferred(); // 生成Deferred对象
  54. $("#block3").animate({
  55. width: "50%"
  56. }, 2000, function() {
  57. dtd.resolve(); // 改变Deferred对象的执行状态
  58. });
  59. return dtd;
  60. }
  61.  
  62. function animate2() {
  63. var dtd = $.Deferred(); // 生成Deferred对象
  64. $("#block4").animate({
  65. width: "50%"
  66. }, 2000, function() {
  67. dtd.resolve(); // 改变Deferred对象的执行状态
  68. });
  69. return dtd;
  70. }
  71.  
  72. var anim = animate1();
  73.  
  74. anim.then(function() {
  75. $("#block3").text('block3动画动画直接结束');
  76. return animate2();
  77. }).then(function() {
  78. $("#block4").text('block4动画动画直接结束');
  79. });
  80.  
  81. });
  82.  
  83.  
  84. </script>
  85. </body>
  86.  
  87. </html>
下一节