ES6 promises特性来自javascript走心的承诺

1,169 阅读7分钟
原文链接: www.shuaihua.cc

首先解释下Promise的中文意思,来自Google的解释:

百度对 承诺 一词的解释:

其中一条释意为:对某项事务答应照办。在一条例句中这样写道 “一切都按预先约定的承若,毫无半点差错。”

所谓一诺千金,也不过如此。

所以,JavaScript 的 Promise 特性允许你请求JavaScript郑重的许下一句诺言,承诺在未来的某一个时机成熟的时刻帮你准确无误的完成某项任务,而此时你则可以继续去做其他的事情,等任务完成后promise回来告诉你承诺的事情完成的怎么样(当然有成功总会有失败,这无可厚非),无论承诺完成的怎么样,promise依然会继续履行对你的承诺(莫名感动啦~)。

程序的世界不会欺骗,每一个函数、方法、属性都那么简单、纯粹、耿直,真好,可完美的就不是这现实世界。

好啦,这是 caniuse.com/#search=pro… 提供的浏览器对 promise 的兼容情况啦。

Promise最初被提出是在E语言中, 它是基于并列/并行处理设计的一种编程语言。

实例化Promise

实例化一个Promise很容易:

new Promise(function(resolve, reject){
	//这里用定时器模拟了一个耗时的操作。
	setTimeout(function(){
		if(异步处理的结果满足条件){
			//执行回调函数resolve。
			resolve(这里可以传入异步处理得到的正确的数据)
			return;
		}
		//如果没有正确完成异步操作则执行reject。
		reject(这里可以传入为什么没有兑现承诺的异常、错误原因);
	}, 500);
})

然而我们不可能每次使用promise的时候都要像上方那样写一大堆东西,比较合理的方式是将上方的代码封装到一个函数中,该函数 return 出promise实例,这样就可以在随后继续操作该函数返回的promise对象了。

比如这样子封装函数:

function asyncFunction(){
	return new Promise(function(resolve, reject){
		//这里用定时器模拟了一个耗时的操作。
		setTimeout(function(){
			if(异步处理的结果满足条件){
				//执行回调函数resolve。
				resolve(这里可以传入异步处理得到的正确的数据)
				return;
			}
			//如果没有正确完成异步操作则执行reject。
			reject(这里可以传入为什么没有兑现承诺的异常、错误原因);
		},500);
	})
}

使用的时候只需要:

var promise = asyncFunction();

便可以得到promise实例啦,当然,具体的函数名称或者方法名称要根据你的需求来定,尽可能起一个让大家一目了然知道其用途的函数名称:

function getArticleDate(){
	//这里用定时器模拟了一个耗时的操作。
	setTimeout(function(){
		return new Promise(function(resolve, reject){
			if(...){
				resolve(...);
				return;
			}
			reject(...);
		})
	}, 500);
}

getArticle().then(...);

点击下方示例的按钮,将会使用 Promises 执行一个模拟的异步请求。

点我~~

但是我们目前还不知道,异步处理的结果是怎么样的(成功 OR 失败),这在下方的 then 方法中会提到如何处理异步请求的结果。

随后可以在该 promise 实例后使用 then 方法,then 方法接收两个参数,分别处理resolve和reject两种情形,具体用法看下方。

Promise#then

promise.then(onFulfilled, onRejected);

需要说明的是, resolve()reject() 如果同时出现在一种结果里,那么会先执行先调用的回调函数。

...
resolve(...);
reject(...);
...

//promise内部会调用开发者注册的 **onFulfilled** 回调函数,并不会调用 **onRejected** 回调函数。因为这里resolve()和reject()函数同时触发了,但resolve()函数在前;反之如果reject()在前则内部直接调用 **onRejected** 回调函数并返回。

fulfilled后缀有ed ,表示已经...,它的的中文释义:已经履行、已经兑现、已经满足、已经完成。所以*onFulfilled***的意思不言而喻,即是 当承诺兑现时执行的回调函数

rejected,有ed表示已经...,它的中文释义:拒绝、抵制、排斥。在这里表示承诺无法兑现,onRejected 表示当承诺无法兑现时执行的回调函数

then代码示例
var promise = new Promise(function(resolve, reject){
    resolve("传递给then的值");
});
promise.then(function (value) {
    console.log(value);
}, function (error) {
    console.error(error);
});

这段代码创建一个promise对象,定义了处理onFulfilled和onRejected的函数(handler),然后返回这个promise对象。

这个promise对象会在变为resolve或者reject的时候分别调用相应注册的回调函数。

  • 当handler返回一个正常值的时候,这个值会传递给promise对象的onFulfilled方法。
  • 定义的handler中产生异常的时候,这个值则会传递给promise对象的onRejected方法。

Promise#catch

promise.catch(onRejected);
catch代码示例
var promise = new Promise(function(resolve, reject){
    resolve("传递给then的值");
});
promise.then(function (value) {
    console.log(value);
}).catch(function (error) {
    console.error(error);
});

这是一个等价于 promise.then(undefined, onRejected) 的语法糖。

Promise.resolve

Promise.resolve(promise);
Promise.resolve(thenable);
Promise.resolve(object);
var taskName = "task 1"
asyncTask(taskName).then(function (value) {
    console.log(value);
}).catch(function (error) {
    console.error(error);
});
function asyncTask(name){
    return Promise.resolve(name).then(function(value){
        return "Done! "+ value;
    });
}

根据接收到的参数不同,返回不同的promise对象。

虽然每种情况都会返回promise对象,但是大体来说主要分为下面3类。

接收到promise对象参数的时候 返回的还是接收到的promise对象。

接收到thenable类型的对象的时候 返回一个新的promise对象,这个对象具有一个 then 方法。

接收的参数为其他类型的时候(包括JavaScript对或null等) 返回一个将该对象作为值的新promise对象。

Promise.reject

Promise.reject(object)
Promise.reject代码示例
var failureStub = sinon.stub(xhr, "request").returns(Promise.reject(new Error("bad!")));

返回一个使用接收到的值进行了reject的新的promise对象。

而传给Promise.reject的值也应该是一个 Error 类型的对象。

另外,和 Promise.resolve不同的是,即使Promise.reject接收到的参数是一个promise对象,该函数也还是会返回一个全新的promise对象。

var r = Promise.reject(new Error("error"));
console.log(r === Promise.reject(r));// false

Promise.all

Promise.all(promiseArray);
Promise.all代码示例
var p1 = Promise.resolve(1),
    p2 = Promise.resolve(2),
    p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then(function (results) {
    console.log(results);  // [1, 2, 3]
});

生成并返回一个新的promise对象。

参数传递promise数组中所有的promise对象都变为resolve的时候,该方法才会返回, 新创建的promise则会使用这些promise的值。

如果参数中的任何一个promise为reject的话,则整个Promise.all调用会立即终止,并返回一个reject的新的promise对象。

由于参数数组中的每个元素都是由 Promise.resolve 包装(wrap)的,所以Paomise.all可以处理不同类型的promose对象。

Promise.race

Promise.race(promiseArray);
Promise.race代码示例
var p1 = Promise.resolve(1),
    p2 = Promise.resolve(2),
    p3 = Promise.resolve(3);
Promise.race([p1, p2, p3]).then(function (value) {
    console.log(value);  // 1
});

生成并返回一个新的promise对象。

参数 promise 数组中的任何一个promise对象如果变为resolve或者reject的话, 该函数就会返回,并使用这个promise对象的值进行resolve或者reject。

啊,其实呢,任何一个新的JavaScript特性都需要你自己去尝试去摸索啊,不要眼高手低,其实不看这篇文章,你就去试错也会有进步啊 XD


觉得还不错的介绍 promise 特性的网站:


最近搬家了,一起合租的小姐姐家养了一只猫,每次回到家都能听到屋里传来猫的嘶吼声,像是饿了一天给急的。所以我就想,宠物和养宠物的人是一种什么样的互利关系?养宠物的意义是什么?去网上搜了一遍,绝大多数是站在人的角度来表述饲养宠物的意义的

可是站在宠物的角度想想,他们被收养的意义是什么呢?他们会有情绪么?我们允许他们有情绪么?他们算是什么呢?玩具?炫耀的资本?

如果主人在领养一只宠物时不能给他一个承诺,那他才真的不算是什么?