Promise 小记(一)

什么是Promise

只要一提到 JavaScript 异步编程,我想绝大多数人都会想到 JS 回调函数。而 ES6 为我们带来了新的异步编程方式——Promise。

Promise并不是JS首创的,而是来源于E语言,它是基于并列/并行处理设计的一种编程语言。Promise 把基于回调的异步处理对象抽象了出来进行规范化,并采用统一的接口对其进行各种操作。这样,基于Promise的统一接口的做法,可以将复杂的异步处理轻松进行模式化,便于我们的维护和使用。

Promise API

构造实例

Promise 是一个构造函数,需要使用 new 操作符构造出一个新 promise 实例作为接口。对 Promise 实例化时可以传入两个参数分别是 resolve 和 reject。 分别用来设置 promise 实例的异步处理成功还是失败。

let promise = new Promise(function (resolve, reject) {
	// 异步处理
	// 调用 resolve 或 reject
})

实例方法

promise.then()

构造 promise 实例后,可以使用 then 方法指定 promise 异步处理结果分别为 resolved 状态和 rejected 状态下的回调函数。它接受两个回调函数作为参数,第一个回调将在 Promise 对象状态变为 resolved 时调用,而第二个回调将在 Promise 对象的状态变为 reject 时调用。其中,第二个参数是可选的。这两个回调都接受 Promise 对象传出的值作为参数。

promise.then(onFulfilled, onRejected);

// 只处理resolved
promise.then(onFulfilled);

// 只处理异常
promise.then(undefined, onRejected);

then方法返回的是一个新的 Promise 实例。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。

promise
	.then(data => JSON.parse(data))
	.then(obj => console.log(obj))

promise.catch()

catch 方法是 promise.then(undefined, onRejected);的别名,用于指定发生错误时的回调函数。Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

promise.then(function () {
	// 回调
}).then(function () {
	// 回调
}).catch(function (err) {
	console.log(err);
})

静态方法

Pomise 全局对象还拥有一些静态方法。如Promise.all() Promise.resolve() Primise.race() Promise.reject()。这些方法都是一些针对 Promise 进行辅助操作的方法。就不一一解释。

Promise 工作流

在介绍了 Promise 的 API 后,我们先来开下面一段代码:

let promise = new Promise((resolve, reject) =>  {
	setTimeout(() => resolve("Hello World"), 100);
})

promise
	.then(msg => console.log(msg))	// => "Hello World"
  	.catch(err => console.log(err));

在上面这段代码中,我们用 new 操作符构造了一个 Promise 实例 promise。promise 会在100ms 后被resolved,这时,then 的回调函数会被调用并输出”Hello World”。而由于 promise 执行了 resolve ,因此 catch 回调不会被执行。

我们可以发现, 在 Promise 的整个工作流中, 调用回调是根据 Promise 的状态决定的。

Promise 实例对象有三种状态:

  • Pending: 进行中, promise 对象实例化后的初始化状态;
  • Resolved(Fulfilled): 已成功,这时会调用 then 方法中的第一个回调函数;
  • Rejected: 失败,这时会调用 then 方法中的第二个回调函数或 catch 的回调。

Promise 的状态从 Pedding 转换为 Resolved 或 Rejected 后,这个 Promise 对象的状态就不再改变。也就是说, Promise 与事件绑定不同,在 then 后执行的函数肯定只会被调用一次。

一个简单的 Promise 应用

下面,我们以一个简单的例子结束这次 Promise 介绍。

我们用 Promise 来处理 XMLHttpRequest 的数据。

const ajax = function (url) {
	return new Promise((resolve, reject) => {
		let req = new XMLHttpRequest();

		req.open("GET", url);

		req.onreadystatechange = function () {
	     	if (req.readyState !== 4 )  return;
	      	if (req.status === 200) {
	       		resolve(req.responseText);
	      	} else {
	        	reject(new Error(req.statusText));
	      	}
	    };

		req.send();
	})
}

ajax("http://exmaple.com")
	.then(data => console.log(data))
	.catch(err => console.error(err));

以上就是一个简单的处理 ajax 的 promise 示例。下次,我将介绍更多 Promise 的使用方法。