如何更优雅的书写Javascript之告别回调地狱

JavaScript06

如何更优雅的书写Javascript之告别回调地狱,第1张

在使用jquery animat做多个动画效果的时候,可能很多的童鞋写出过如下的代码。

代码如下复制代码

// 在前一个动画执行完成后,紧接着执行下一个动画

$('xx').animate({xxxx}, function(){

$('xx').animate({xx},function(){

//do something

},1000)

},1000)

由上面的代码可以看出,目前有2层的回调嵌套。

那我们思考下,如果我们有3个,4个或是更多的动画效果要紧接着执行,

我们是不是就发现,我陷入了无尽的回调地狱里去了呢?

可以访问这里看看我们平常会写出的一些回调 更多例子:js代码中的回调地狱

那么,到这里,大家看到了,大量的回调函数嵌套,

不仅仅让代码显得更加难看、臃肿,也让项目变得越来越不好维护。

相信用过JS的都知道JS是单线程的,同步的函数先执行,异步的函数先加入到一个队列中等同步执行完了再执行异步函数。基于这个JS采用异步回调的方式来处理需要等待的事件,是的代码会继续执行而不用在异步处理的地方一直等待着。同时也带来一个不好的方面,如果我们有很多的回调函数, 也就是说一个回调函数里边再嵌套一个回调一层一层的嵌套,这样就很容易进入传说中的回调地狱。

注意:异步和回调不是一个东西

下面感受一下回调地狱代码的魅力:

是挺有美感的但是阅读性很差,写法也让人感到无力,es6新出的promise对象已经es7的async await都可以解决这个问题,但是今天的主角是Promise。

Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有一下两个特点:(1)对象的状态不受外界影响;(2)一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。Promise有三种状态,分别是:Pending(进行中),Resolved(完成),Rejected (失败)。Promise从Pending状态开始,如果成功就转到成功态,并执行resolve回调函数;如果失败就转到失败状态并执行reject回调函数。

Promise一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

Promise构造函数接收一个函数作为参数,该函数的两个参数是resolve,reject,它们由JavaScript引擎提供。其中resolve函数的作用是当Promise对象转移到成功,调用resolve并将操作结果作为其参数传递出去;reject函数的作用是单Promise对象的状态变为失败时,将操作报出的错误作为其参数传递出去

介绍一下Promise的api怎么使用:

1、Promise.resolve()的作用将现有对象转为Promise对象resolvedPromise.resolve('test')==new Promise(resolve=>resolve('test'))

2、Promise.reject()返回一个Promise对象,状态为rejected

3、Promise.prototype.then()方法接受两个参数,第一个是成功的resolved的回调,另一个是失败rejected的回调,第二个失败的回调参数可选。并且then方法里也可以返回promise对象,这样就可以链式调用了。

4、Promise.prototype.catch()发生错误的回调函数。

5、Promise.all() // 所有的事都有完成,相当于 且,适合用于所有的结果都完成了才去执行then()成功的操作。

6、Promise.race() // 完成一个任务即可,相当于 或。(这个经常用在一些图片比较多的网站)