- Promise 的含义
Promise 是异步编程的一种解决方案,可以把promise 看作一位‘先知‘,可以预测到未来将要发生的事情,从语法来说,Promise是一个对象,从它可以获取异步操作的信息
2.Promise 的特点
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败),只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的改变只有两种可能,从pending-fulfilled 和 pending-rejected 。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为resolved(已定型),如果改变已经发生了,再对Promise 对象添加回调函数,也会立即得到这个结果
Promise 对象可以将异步操作的流程以同步操作的流程表达出来,避免了层层嵌套的回调函数 - Promise 的缺点
无法取消Promise,一旦新建它就会立即执行,无法中途取消;
其次如果不设置回调函数,Promise 内部抛出的错误不会反应到外部 - 基本用法
ES6规定,Promise 对象是一个构造函数,用来生成Promise 实例
const promise = new Promise(function(resolve,reject){
if(true){
resolve(value);
}else{
reject(error);
}
})
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是resolve、reject,他们是两个函数,由javascript 引擎提供,不用自己部署
resolve函数:在异步操作成功时调用(pending-resolved),并将异步操作的结果作为参数传递出去;
reject 函数:在异步操作失败时调用(pending-rejected),并将异步操作报出的错误作为参数传递出去;
5. Promise.prototype.then()
Promise实例生成之后,可以用then 方法分别指定 resolved 状态和 rejected 状态的回调函数,then方法是定义在原型对象Promise.prototype 上的,作用是为Promise实例添加状态改变时的回调函数,then 可以接受两个回调函数作为参数,第一个回调函数是Promise 对象的状态变为resolved 时调用,第二个回调函数是Promise对象的状态变为rejected时调用(参数可选)
function ajax(obj){
const promise = new Promise(function(resolve,reject){
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Miscrosoft.XMLHTTP');
if(obj.method.toUpperCase() == 'GET'){
xhr.open('GET',obj.url + '?' + obj.data,true);
xhr.send(null);
}else if(obj.method.toUpperCase() == 'POST'){
xhr.open('POST',obj.url,true);
xhr.send(obj.data);
}
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
xhr = xhr.responseText;
console.log(xhr);
resolve(xhr);
}else{
reject(new Error());
}
}
})
return promise;
}
ajax({
method : 'GET',
url : './tsconfig.json',
data : ''
}).then(function(json){
console.log(json);
},function(error){
console.log('error:',error);
}).catch(function(){
console.log('111');
})
//ajax() 是对XMLHTTPRequest对象的封装,用于发起一个针对JSON数据的HTTP请求,并且返回一个Promise对象,如果调用resolve函数和reject函数时带有参数,那么他们的参数就会被传递给回调函数
//调用resolve 或 reject 并不会终结Promise 的参数函数的执行
new Promise((resolve,reject) => {
resolve(1);
console.log('2');
}).then(res => {
console.log('1');
})
// 2
//1
//上面调用完resolve(1) 函数,还能打印出来2,说明resolve后面的代码还是会执行,并且会首先打印出来,这是因为resolved 的Promise 是本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。所以为防止意外发生最好在它们前面加上return 语句
new Promise((resolve,reject) => {
return resolve(1);
console.log('2'); //此处的代码就不会被执行
}).then(res => {
console.log('1');
})
- Promise.prototype.catch()
Promise.prototype.catch()方法是.then(null,rejection)的别名,用于指定发生错误时的回调函数,一般来说不要在then方法里定义Reject状态的回调函数,总是使用catch方法,建议这样写
promise.then(function(data){
//执行成功的回调函数
}).catch(function(err){
//执行失败的回调函数
})
new Promise((resolve,reject) => {
resolve(1);
console.log('2');
}).then(res => {
console.log('1');
}).catch(function(error){
console.log('error:' + error)
}).then(function(val){
console.log('last...')
})
// 2
// 1
// last...
如果代码中没有报错,则会跳过catch方法
- Promise.all() : 用于将多个Promise 实例,包装成一个新的Promise实例
Promise.all() 参数的方法可以不是数组,但必须具有Iterator 接口,且返回的每个成员都是Promise 实例
const p = Promise.all([p1,p2,p3]);
//只有当p1 p2 p3 的状态都为fulfilled,p的状态才会变成fulfilled,只要其中有一个被rejected,p 的状态就会变成rejected
- Promise.race()
const p = Promise.race([p1,p2,p3]);
//上述代码中只要有一个实例状态改变,p 的状态就跟着改变