promise
Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。Promise 是异步编程的一种解决方案,比回调函数和事件更合理更强大。使用Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
用法
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供。resolve函数在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
注意:Promise 新建后就会立即执行。一般来说,并不需要它立即执行,应该是在需要的时候调用它,然后执行。所以,用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数,如:
function runPromise(){
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
return promise;
}
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数:
promise.then(function(value) {
// success
}, function(error) {
// failure
});
第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
function runPromise(data){
var promise = new Promise(function(resolve,reject){
setTimeout(()=>{console.log("任务一");resolve(data)},2000)
});
return promise
}
runPromise("想传递的数据").then(function(data){
console.log(data);
})
//任务一
//想传递的数据
链式调用
Promise 实例具有then方法,为 Promise 实例添加状态改变时的回调函数。返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法:
function runPromise(task,data){
var promise = new Promise(function(resolve,reject){
setTimeout(()=>{console.log(task);resolve(data)},2000)
});
return promise
}
runPromise("任务1","想传递的数据1").then(function(data){
console.log(data);
return runPromise("任务2","想传递的数据2")
}).then(function(data){
console.log(data)
})
//任务1
//想传递的数据1
//任务2
//想传递的数据2
也可以直接return数据而不是Promise对象,这样后面的then中就可以只接收数据。
错误处理
Promise对象除了then方法,还有一个catch方法来处理错误,效果和写在then的第二个参数里面一样。另外,在执行resolve的回调时,如果代码出错了,那么并不会报错卡死js,而是会进到这个catch方法中:
runPromise("任务1","想传递的数据1").then(function(data){
console.log(data);
console.log(error)
}).catch(function(reason){
console.log(reason)
})
//任务1
//想传递的数据1
//ReferenceError: error is not definedat test.html:71
Promise 对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。因此,不需要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),只需要在多个then方法最后添加catch方法就可以。
ajax
用Promise对象实现的 Ajax 操作的例子:
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 {
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("/example.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});