说明
我们都知道JavaScript是单线程的,这意味着任何两句代码都不能同时运行,它们得一个接一个来。在浏览器中,JavaScript 和其他任务共享一个线程,不同的浏览器略有差异,但大体上这些和 JavaScript共享线程的任务包括重绘、更新样式、用户交互等,所有这些任务操作都会阻塞其他任务。
作为人类,你是多线程的。你可以用多个手指同时敲键盘,也可以一边开车一遍电话。唯一的全局阻塞函数是打喷嚏,打喷嚏期间所有其他事务都会暂停。很烦人对么?尤其是当你开着车打着电话的时候。我们都不喜欢这样打喷嚏的代码。尤其是在浏览器环境中往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。为了解决这个问题,Javascript语言将任务的执行模式分成两种:
“同步模式”就是后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;”异步模式”则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。
“异步模式”非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。在服务器端,”异步模式”甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有http请求,服务器性能会急剧下降,很快就会失去响应。
而在异步模式中Promise的出现无疑是一件让人欢呼雀跃的事,这是为什么呢?
什么是Promise
一个promise代表了异步操作的最终结果,promise交互的主要方法是通过.then
方法。Promise对象其实是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
Promise对象有以下几种状态:
- pending: 初始状态, 既不是 fulfilled 也不是 rejected.
- fulfilled: 成功的操作.
- rejected: 失败的操作.
这里要稍微拓展一点小知识,不知道你有没有听过薛定谔的猫。大体的意思是说在一个盒子里有一只猫,以及少量放射性物质。之后,有50%的概率放射性物质将会衰变并释放出毒气杀死这只猫,同时有50%的概率放射性物质不会衰变而猫将活下来。你永远的不会知道猫是死还是活在盒子未被打开前。这一点和promise的机制很相似,也就是说在异步回调返回之前,程序是无法知道结果是成功还是失败,因此我们给出了相应的预处理。
pending状态的promise对象既可转换为带着一个成功值的fulfilled 状态,也可变为带着一个失败信息的 rejected 状态。当状态发生转换时,promise.then
绑定的方法(函数句柄)就会被调用。(当绑定方法时,如果 promise对象已经处于 fulfilled 或 rejected 状态,那么相应的方法将会被立刻调用, 所以在异步操作的完成情况和它的绑定方法之间不存在竞争条件。)
因为Promise.prototype.then
和 Promise.prototype.catch
方法返回 promises
对象, 所以它们可以被链式调用—— 一种被称为 composition 的操作。
Promise的常见用法
- 与XMLHttpRequest结合使用
1 | ; |
上面代码其实是javascript的一种设计模式,详细可阅读Learning JavaScript Design Patterns。适配器模式的作用是解决两个软件实体间的接口不兼容的问题。使用适配器模式之后,原本由于接口不兼容而不能工作的两个软件实体可以一起工作。适配器的别名是包装器(wrapper),这是一个相对简单的模式。通过适配器模式将传统的xhr请求封装成restful风格然后返回Promise进一步方便链式调用。
- 用于图片加载
See the Pen promise-test by Gnipbao (@Gnipbao) on CodePen.
如果你想系统的学习promsie
的话建议你去看promise迷你书写的相当不错。
最后推荐一个不错的promise
库ES6-Promise。