1. 简介
promise
(承诺),异步编程的一种解决方案,比传统的解决方案,回调函数和事件——更合理和更强大。
promise
一种容器,里面保存着某个未来才会结束的事件(通常是一个异步操作),就像它的中文一样(承诺),许下的承诺;
-
状态
promise
有三种状态:pending
(进行时),fulfilled
(已成功),rejected
(已失败)。
erDiagram
Promise ||--o{ fulfilled : pending
Promise }|..|{ rejected : pending
特点
对象的状态不受外界的影响;
promise
对象代表的是一个异步操作;它的三种状态不受外界的影响,只有异步操作的结果,可以决定当前是哪一种状态;任何其他操作都无法改变。
一旦状态改变,就不会再变,任何时候都可以得到这个结果。
Promise
一旦执行,无论结果如何,都会被记住。任何时候提起都是(resolved
)已定型的;从pending
变为fulfilled
,pending
变为rejected
.如果改变已经发生,再用回调函数获取Promise
这个状态,是可以获取到的;这个和事件(event
)不同,事件(event
)一旦你错过了它,想要监听得到结果,是不可能的。
缺点:
Promise
一旦执行,无法取消;- 如果没有设置回调函数,
Promise
内部抛出的错误,不能反映到外部; - 当处于
pending
状态时,无法知道当前是处于什么状态,(刚开始,还是快结束。)
2. 基本用法
声明一个 Promise 实例
// Promise 实例接收两个参数 resolve,reject
var Promise = new Promise( function ( resolve,reject ) {
if ( /* 异步操作成功的判断 *) {
// value成功接收的参数
resolve(value);
} else {
// value失败接收的参数
reject(value);
};
})
Promise
构造函数接受一个函数作为参数,这个函数接受resolve
和rejected
作为参数。它们是两个函数,由Javascript
引擎提供。
resolve
的作用,是将Promise
对象的状态从“pending
”变为“resolve
”,在异步成功时调用,并将异步操作的结构,作为参数传递出去;rejected
的作用,是将promise
对象的状态从“pending
”变为“rejected
”,在异步失败时,将异步操作的结果,作为参数传递出去;
调用
Promise
生成example
以后,可以用then
方法分别指定resolve
和rejected
状态的回调函数;这两个函数都是可选的,不一定要提供;
Promise.then( ( value ) => {
// resolve的回调函数
},( error ) => {
// rejected的回调函数
})
注意:调用 resolve
和 reject
并不会终结 Promise
的参数函数的执行。
new Promise((resolve, reject) => {
return resolve(1);
// 后面的语句不会执行
console.log(2);
})
- 创建一个 ajax case,后面要做引用
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
console.log();
reject(new Error(this.statusText ));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
3. Promise.prototype.then()
Promise
实例具有then
方法,then
方法是定义在原型对象Promise.prototype
上的,作用是为promise
实例添加状态改变时的回调函数;
then
方法返回的是一个新的Promise
实例函数;可以采用链式写法,then
方法后面再跟一个then
方法。
getJSON('/posts.json').then( (json) => {
return json.post;
}).then( ( post) => {})
4.Promise.prototype.catch()
Promise.prototype.catch()
方法是.then(null,rejection)
或.then(undifined,rejection)
的别名,在发生错误时的回调函数;resolve
失败时的回调,或者接口函数调用失败时的回调函数;
// Promise.prototype.catch()的使用
getJSON('/post.json').then( (posts) => {
//成功时的处理函数
}).catch( ( error ) =>{
//处理 getJson 和前一个回调函数失败时的发生的错误
console.log(error);
})
- 使用
.then
链式写法处理错误
p.then( (val) => console.log('fulfilled:',val))
.catch( ( err ) => console.log('rejected:',err));
// 等同于
p.then( ( val ) => console.log('fulfilled:',val))
.then( null,( err ) => console.log('rejected:'.err));
前面有说过,.then()
返回的是一个promise()
函数,所有.then()
链式写法可以处理上一个.then()
方法返回的Promise
回调函数事件;
- case
var Promse1 = new Promise( ( resolve,reject) => {
// 抛出一个错误
throw new Error('test')
});
// 监听
Promse1.catch( ( error ) => {
console.log(error);
})
// Error:test
- 使用try catch 结合 rejecte 抛出错误
var promise2 = new Promise( ( resolve,reject ) => {
try {
console.log('caught error');
throw new Error('test1')
} catch( e ) {
// 使用rejecte接收 e 错误,并作为参数抛出
reject(e);
};
});
// 监听
promise2.catch( ( error ) => {
console.log(error);
})
- 使用 reject 捕获错误 并当参数抛出
var promise3 = new Promise( ( resolve,reject ) => {
reject( new Error('test3'));
});
// 监听
promise3.catch( ( error ) => {
console.log('%c 使用reject抛出的错误:' + error,'color:red');
});
// 使用reject抛出的错误:Error: test3
- 当 promise 状态已经变成 resolve 时,再抛出错误是不能捕获的,因为当 promise 状态一旦改变就永远保持不变。(承诺的结果一旦失败或成功,留给后人的永远只有一个结果。)
var promise4 = new Promise( ( resolve,reject ) => {
resolve(' status is ok ');
throw new Error('test4');
});
promise4.then( ( resolve ) => console.log(resolve))
.catch( ( error ) => console.log(error));
// status is ok
- 冒泡
promise
对象的错误有“冒泡”性质,会一直向后传递,直到被最后一个catch()
方法捕获;
getJSON('/post/1.json').then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 处理前面三个Promise产生的错误
console.log(error);
});
上面的代码中有三个promise
对象产生,一个由getJSON()
函数,还有两个then()
方法产生
Loading~~~