转载

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

Promise是专门给异步计算用的对象,它表示一个现在还没结果,但将来会给你算出来结果来的操作。

没有大肚子的人生是更好的人生

权尾珍

憋说话,看图....

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

图片中的姑娘是韩国搞笑艺人权尾珍,其实她是一位谐星,体重曾经高达103公斤!后来参加了韩国一个减肥真人秀的节目,用三年时间减重51公斤。瘦下来后,权尾珍通过杂志专栏、电台、博客向大众分享了她的减肥经验,“权式减肥法”也开始风靡韩国。

菲涅尔透镜

你们小时候是不是都拿放大镜照过蚂蚁?!所以你们应该都知道什么叫凸透镜吧?菲涅尔透镜也是一种凸透镜,不过它和一般的凸透镜不一样。它不喜欢普通透镜那种胖胖的身材,所以立志减肥,成功瘦身成了一枚纤细的透镜。至于它为什么叫菲涅尔透镜,跟科学界的其他产物一样,因为它是由法国物理学家奥古斯汀.菲涅尔(Augustin.Fresnel)发明的。那是在1822年,菲涅尔第一次把这种透镜用在了灯塔上。哦,估计也只有用在灯塔上才能体现它身材上的优势。

菲涅尔瘦身成功并不是靠慢跑,也不是靠举铁,更不是靠节食。它主要靠抽脂......科学总是有道理的,我们都知道,光的折射是发生在两种介质相互接触的表面的,(比如玻璃透镜的表面),在一种介质内部是不会发生折射的,所以菲涅尔保留了透镜表面的弯曲度,把里面的东西掏空,把鼓鼓的透镜压扁,变成菲涅尔透镜。理论上是像下面这样:

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

按照这个理论做出来的菲涅尔透镜是这样的:

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

很瘦,但依然聚光。

有承诺,没肚子

小姑娘要减肥大家已经司空见惯了。可是你看,连一块透镜都知道要瘦身,我们怎么还好意思不锻炼呢?你可能会说我们码农天天加班没时间,那么问题来了。既然你把时间都用在了代码上,怎么还好意思让自己的代码里到处都是挺着大肚子的Callback调用链呢?不就是要按顺序执行几个异步计算吗?有必要非把自己代码的肚子搞大吗?作为一名负责任的码农,该采取措施还是要采取措施的,把Promise用起来,去掉Pyramid of Doom,还代码一个平坦的小腹,好不好?

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

Promise

Promise是专门给异步计算用的对象,很早之前就作为神技在几大门派间流传,ES6之后被纳入官库。也就是说现在可以像下面这样直接在代码中定义:

new Promise(function(resolve,reject) {     console.log("Start");           window.setTimeout(function() {       resolve();     }, 2000);     console.log("Waitting");       }).then(function() {     console.log("Finished!"); }); 

把上面的代码复制到Chrome开发者工具的控制台中执行,得到的结果是这样的:

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

上面的代码看起来还不太直观,我们来分解一下:

/**  * 执行异步操作的函数,2秒后调用  * 它的回调函数resolve  */ function asyncMission(resolve) {    window.setTimeout(function() {       resolve();     }, 2000); }  /**  * 发起异步操作的函数  *  @param  {function} resolve   *       异步操作成功时调用的回调函数  *  @param  {function} reject   *       异步操作失败时调用的回调函数  */ var executor = function(resolve,reject) {     console.log("Start");         asyncMission(resolve);     console.log("Waitting"); } /**  * 创建一个Promise对象,参数为发起  * 异步操作的那个函数executor  */ var promiseMission = new Promise(executor);      /**  * 神秘的resolve终于现身了!  * 你可以把方法then的第一个参数  * 当作resolve  */    promiseMission.then(function() {     console.log("Finished!"); }); 

看完上面这段代码,再来看看 MDN上对Promise的定义 :

The Promise object is used for asynchronous computations. A Promise represents an operation that hasn't completed yet, but is expected in the future.

看不懂英文没关系,这不正好我在嘛!给你翻译一下,用中国话说,定义一个 Promise 就相当于老大跟你说:“你出趟远门,老子有个异步计算的差事要交给你办,事成之后, ____________ "。看到没,给了张空白支票!!!而 then 就是让你填那个空的方法,事成之后你想干什么,告诉 then 就成了。

不过你应该知道的,老大都是很有原则的人,不会像我上面写的代码一样,只告诉你事成之后可以怎么样。说完好处,他的脸上一定还会浮现出讳莫如深的、蛋蛋的忧伤,告诉你办不成应该怎样。所以一个完整的 Promise 应该是这样的:

var p1 = new Promise(     function(resolve, reject) {                     window.setTimeout(             function() {                 resolve(Math.random());             }, 2000);     } );  p1.then(       // resolve,val就是上面那个Math.random()的值       function(val) {          console.log(val);       })    .catch(       // reject       function(reason) {          console.log('搞砸了,',reason);       }); 

Promise一直都知道,在经过漫长的 pending 之后,事情总会有 settled 的时候。但 settled 的结果,有可能是 fulfilled ,也有可能是 rejected 。所以我们可以用 then 告诉它事成之后怎么办,也可以用 catch 告诉它失败了怎么办。关于 Promise ,我要说的这么多;不过关于 then ,还有很多话要说。

then(what)?

then 是减掉大肚子的关键,看清了then是什么,就算是掌握了Promise的奥义。来,请看 MDN中对then的定义 :

The then() method returns a Promise. It takes two arguments: callback functions for the success and failure cases of the Promise.

所有的秘密都在第一句话里......

在前面所有的代码里,都隐藏着一个很容易被忽视的事实, then 也是有返回值的,而且它返回的就是 Promise !不要忘了,我们看到的那个函数只是它的参数,不管它的参数有没有返回值, then 都会返回一个Promise。我们可以简单地把then的实现理解成下面这个样子:

 then(resolve,reject) {    var val = resolve();    return new Promise(       function(_resolve,_reject) {          _resolve(val)    });  } 

所以整个故事大概是这样的:开始创建Promise的时候,我们只知道它的参数是一个函数,而这个函数的参数是两个回调函数。这两个回调函数一个是在Promise被 fulfilled 时调用的resolve,一个是Promise被 rejected 时调用的reject;但这两个回调函数具体长什么我们并不知道。然后 then 登场了,它的参数就是那个神秘的resolve回调函数。哦,对, then 也可以用第二个参数指出reject是谁,但那是2B码农的写法,优雅的程序猿轻易不会露出那么急赤白脸的吃相,reject应该作为 catch 的参数出现。

既然 then 返回的是 Promise ,那 then (和 catch )之后就可以接着 then (和 catch ),然后再 then (和 catch ),这样callback的调用就可以从回调函数里提出来,放到 then 中去,回调函数的调用链就变成平坦的了。

HTML、CSS及JavaScript : 有Promise,不会搞大肚子

当然,我们都知道,健身不光能让体型好看,还有很多额外的好处,比如血压血脂胆固醇什么的。用Promise写代码也有很多额外的好处,我就不说了,留着你自己慢慢体会吧。

最后,为了感谢你有看这么长时间的耐心,整点干货。

PyramidOfDoom VS chainedThen

憋说话,看代码:

function mission(duration,callback) {   console.log(`Mission ${duration/1000} Start at ${Date.now()}`);   window.setTimeout(function() {     console.log(`Waitting Mission ${duration/1000}`);     callback(duration);   }, duration); }  (function pyramidOfDoom() {   mission(1000,function() {     console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);     mission(2000,function() {       console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);       mission(3000,function() {         console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);         mission(4000,function() {           console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);           mission(5000,function() {             console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);             mission(6000,function() {               console.log("All missions Completed!");             })           })         })       })     })   }); })(); 

再看这个:

function promiseMission(duration) {   console.log(`Mission ${duration/1000} Start at ${Date.now()}`);   return new Promise(function(resolve,reject) {     window.setTimeout(function() {       resolve(duration);       console.log(`Waitting Mission ${duration/1000}`);     }, duration);   }); }  promiseMission(1000)   .then(function(duration) {     console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);     return missionPromise(duration+1000);   })   .then(function(duration) {     console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);     return missionPromise(duration+1000);   })   .then(function(duration) {     console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);     return missionPromise(duration+1000);   })   .then(function(duration) {     console.log(`Mission ${duration/1000} Complete at ${Date.now()} after ${duration}`);     return missionPromise(duration+1000);   })   .then(function() {     console.log("All missions Completed!");   }) 

最后再安利一个教程,优达学院有个免费的 JavaScript Promise 课程可以看看。

还有我的公众号,也可以关注一下: HTML、CSS及JavaScript : 有Promise,不会搞大肚子

原文  http://www.ituring.com.cn/article/217606
正文到此结束
Loading...