Learning Card
- 同步VS异步
- JS是单线程语言
- 主线程处理同步,异步操作在满足触发条件时加入到任务队列中
Promise
用来处理异步操作
- Promise是什么
- 一个容器,里面包含未来才会结束的事件
- 用法
Promise
构造函数- 包含
resolve
和reject
两个函数
- 方法
Promise.prototype.then()
Promise.all()
Promis.race()
- 同步VS异步
同步 VS 异步
JS是单线程的语言,它的主线程用来执行代码中的同步任务,无法立即执行的异步任务会由不同的线程来处理,如定时器触发线程,异步http请求线程,但最终,这些任务在满足触发条件之后,都会被放入由事件触发线程管理的任务队列中。在主线程空闲时来处理任务队列中的任务。
Promise就是来处理异步操作的,即处理最终什么样的任务会被添加到任务队列中去。
Promise是什么
- 解决异步的一种方法
- 本质:一个容器,里面包含着某个未来才会结束的事件
- 特点:
- 对象的状态不受外界影响
- 三种状态:
pending
,fulfilled
,rejected
- 只有异步操作的结果可以决定当前是哪一种状态
- 我们可以这样理解,一个Promise对象包含了一个处于
pending
状态的任务,这个任务根据自身的内容可以被归类到不同的线程中,我们通过在Promise内部的代码进行判断,决定任务的结果是成功fulfilled
还是失败rejected
,无论是成功还是失败,它们都有对应的回调函数,Promise解决的就是在判断之后将对应的回调函数加入到任务队列中去
- 三种状态:
- 一旦状态改变,就不会再变
pending
=>fulfilled
pending
=>rejected
- 对象的状态不受外界影响
- 缺点:
- 无法取消
- 必须设置回调函数,否则抛出错误
- 处于
pending
状态时,无法得知目前进展到哪一个阶段
基本用法
1 | const promise = new Promise(function(resolve, reject) { |
Promise
对象有两个参数,resolve
表示成功,reject
表示失败,它们都接受一个返回值,resolve
接收到的返回值是任务反馈回来的数据value
,reject
接收到的是error
错误本身。
但是这只定义了promise
对象,并没有将回调函数加入到任务队列中去,执行完成promise
还需要用后面的方法。
方法
Promise.prototype.then()
Promise.prototype.then()
方法就是用来添加状态改变时的回调函数。它同样有两个参数,一个是resolve
成功时的回调函数,一个是reject
失败时的回调函数。相当于Promise
构造函数部分决定了什么条件下算成功,什么条件下算失败,.then()
方法明确了成功和失败各自情况下会有什么操作,非常明了。
1 | const getJSON = function(url) { |
以上是一段AJAX请求的代码,里面将返回的内容封装到一个Promise
对象中,请求成功时得到的是this.response
数据,失败时使用的是this.statusText
错误状态码来作为回调函数的值。接下来我们可以用.then()
方法来处理这个promise
对象
1 | getJSON("/posts.json").then(function(json) { |
需要注意的是,Promise.prototype.then()
返回的是一个新的Promise
对象,因此在.then()
方法后面可以再添加新的.then()
方法来处理新的数据,使用链式then
如果我们需要连续地请求一连串的数据时,Promise
方法会使得这些请求写起来非常地简单,有种使用同步的写法来实现异步操作的感觉。
Promise.all()
Promise.all()
方法用于将多个Promise
实例包装成一个新的Promise
实例。
1 | const p = Promise.all([p1, p2, p3]); |
还是借用上面的getJSON
的例子,如果我们要读取”/posts/1.json”,”/posts/2.json”,”/posts/3.json”,”/posts/4.json”…,我们可以这样做
1 | getJSON("/posts/1.json").then(function(json) { |
但是这样明显会麻烦很多,我们也可以用简单一些的方法
1 | const promises = [1, 2, 3, 4, 5, 6].map(function(id) { |
我们可以通过Promise.all()
来把所有的promises解析出来,它接受一个数组作为参数,也返回一个包含了各个Promise
返回的数据的数组作为resolve
回调函数的参数,这时,我们可以通过解构赋值来将每个Promise
对应的数据解析出来,从而可以单独操作每个Promise
返回的数据。
此外,jQuery的高级版本中是包含了Promise
对象的,也就是说,我们在使用比如ajax请求的时候,可以直接使用Promise.all
方法,而不用先构造Promise
对象。
1 | Promise.all([ |
Promise.race()
Promise.race()
同样是将多个Promise
的实例包装秤一个新的Promise
的实例,不过它是根据参数数组中最先改变状态的Promise
来改变返回值。
ES6学习笔记的内容主要基于阮一峰老师的《ECMAScript 6入门》,原文请见链接