Promise
初步了解Promise
参考链接:
jQuery中的异步操作管理
$.ajax()
对象
说明:主要用于异步请求,提供了success等Deferred的语法糖。
常用方法:
- success
- error
- complete(指无论success或者error都会执行的操作。)
- ...
示例(偷懒,直接从项目代码中接下来了0_0,看个样子就好。)
//complete
{
//...
getEngageTimeData: function (){
var _self = this;
$.ajax({
type:'POST',
url:baseUrl + 'getShowDatetime',
data:{},
success: function (response){
var response = JSON.parse(response);
if(response.status == 0){
_self.renderEngageTime(response);
}
},
error:function(){},
complete: function (msg){
console.log('总是会执行的方法', msg);
}
});
}
}
//then
{
//...
getEngageTimeData:function (){
var _self = this;
$.ajax({
type:'POST',
url:baseUrl + 'getShowDatetime',
data:{}
}).then(function (response){
var response = JSON.parse(response);
if(response.status == 0){
_self.renderEngageTime(response);
}
}, function (){
console.log('发生错误');
});
}
}
$.ajax()方法返回的对象不含resolve、reject等方法。
$.Deffered()
对象
说明:主要是对异步操作的管理,实现了Promise规范。
常用的方法:
- done
- fail
- always
- then
- ...
它的方法与ajax对象的方法的对应关系是:
graph LR
done-->success
fail-->error
always-->complete
then-->function(done, fail)
Deffered方法-->ajax方法返回的是受限的Deffered对象
$.when
jQuery的全局方法
说明:异步操作并行执行,然后执行回调。
示例:
function async1() {
var defer = $.Derferred();
setTimeout(function() {
console.log(1);
defer.resolve('1');//'1':参数表示异步操作返回的数据;
}, 1000);
return defer.promise();
}
function async2() {
//...
}
function async3() {
//...
}
$.when(async1(), async2(), async3()).then(function(data1, data2, data3) {
console.log('执行完毕');
console.log(data1, data2, data3);
});
ES6(也就是ES2015)中的Promise规范
首先看图:
可以看出Promise为一个构造函数,包含all、race、reject、resolve这四个主要的方法。其中:
all对应$.when,可以管理多个异步操作的并行执行,然后等最慢的那个异步操作执行完毕后,执行回调。
var async1 = function() {
var p = new Promise(function(resolve, reject) {
//异步操作
resolve(data); //异步操作返回的data数据
});
return p; //因为使用new构造器时,会立即开始执行异步操作,所以需要包装在async1函数中,通过调用该函数执行想要进行的异步操作。
};
//$.when
$
.when(async1(), async2())
.then(function(data1, data2) {
console.log('所有异步操作执行完毕');
console.log(data1, data2); //各个异步操作返回的data值作为回调函数的参数。
});
//Promise.all
Promise
.all([async1(), async2()])
.then(function(data) {
console.log('所有异步操作执行完毕');
console.log(data); //data数组:n个异步操作返回的data值组成的数组。
});
race也可以管理多个异步操作的并行执行,和all不同的是:race是等待最快的那个异步操作执行完毕后,执行回调
。
var async1 = function() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('async1');
resolve('1');
}, 1000);
});
return p;
};
var async2 = function() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('async2');
resolve('2');
}, 2000);
});
return p;
};
var async3 = function() {
var p = new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('async3');
resolve('3');
}, 3000);
});
return p;
};
Promise
.race([async1(), async2(), async3()])
.then(function(data) {
console.log('执行回调');
console.log(data);
});
//输出顺序为:
//async1
//执行回调
//1
//async2
//async3
reject一般用来处理异步操作过程中报错的情况,通常和catch
配合使用
ps:
catch
方法和try{}catch(e){}
中的catch类似,用来执行reject的回调
或者捕获resolve回调执行过程的错误信息
,并进行处理。
//情形一
var async1 = function() {
var p = new Promise(function(resolve, reject){
setTimeout(function() {
console.log('123');
if(true) {
reject('出错误了');
}else {
resolve('1');
}
}, 1000);
});
return p;
};
async1()
.then(function(data) {
console.log('执行结果', data);
})
//作为reject的回调执行
.catch(function(msg) {
console.log('错误信息:', msg);
});
//输出信息
//123
//错误信息:出错误了
//情形二
var async2 = function() {
var p = new Promise(function(resolve, reject){
setTimeout(function() {
console.log('123');
if(false) {
reject('出错误了');
}else {
resolve('2');
}
}, 2000);
});
return p;
};
async2()
.then(function(data) {
console.log('执行结果', data);
console.log(zgatry); //未定义变量
})
//捕获resolve的回调执行过程中发生的错误。
.catch(function(msg) {
console.log('错误信息:', msg);
});
//输出信息
//123
//执行结果2
//错误信息:ReferenceError: zgatry is not defined at <anonymous>:16:17
ps:执行回调的过程中的错误信息需要通过
catch
来捕获,否则error
会冒泡到全局环境下。
resolve和$.Deferred().resolve
方法用法类似。
链式调用
var async1 = function() {
var p = new Promise(function(resolve, reject){
setTimeout(function() {
if(false) {
reject('1出错误了');
}else {
resolve('1');
}
}, 1000);
});
return p;
};
var async2 = function() {
var p = new Promise(function(resolve, reject){
setTimeout(function() {
if(false) {
reject('2出错误了');
}else {
resolve('2');
}
}, 2000);
});
return p;
};
async1()
.then(function(data1) {
console.log('第一步执行完毕data1:', data1);
//console.log(error1);
return async2();
})
.then(function(data2) {
console.log('第二步执行完了data2:', data2);
//console.log(error2);
})
.catch(function(reason) {
console.log('错误信息', reason);
});
执行结果:
如果取消error1和error2的注释,则执行结果如下:
说明:前面的异步操作发生错误(执行了reject回调或者resolve回调中发生未知错误)会直接跳过后面的所有操作,由catch捕获并处理错误信息。
Promise回顾和补充
- Promise是对延迟(deferred)和异步(asynchronous )操作的管理,可以在Js的同步代码中为某个异步操作完成后,执行回调。通过Promise对象封装,可以实现异步代码的扁平化管理,看起来更加优雅,也更符合书写逻辑,提高代码的可读性。
- Promise对象有三种状态
- pending:初始状态
- fulfilled:成功的操作
- rejected:失败的操作
- 术语补充
promise
是一个包含了兼容promise规范then方法的对象或函数,thenable
是一个包含了then方法的对象或函数。value
是任何Javascript值。 (包括 undefined, thenable, promise等).exception
是由throw表达式抛出来的值。reason
是一个用于描述Promise被拒绝原因的值。
- 浏览器兼容性
- 原生的Promise对象仅支持ES5的现代浏览器可以使用。
- jQuery的$.Deferred对象是从jQuery1.5.0版本开始引入的。
持续补充。
time:2016-12-13
行为影响状态,状态影响视图