Promise
-
基本使用
//resolve和reject是JavaScript引擎提供的两个函数 const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
//用then方法分别指定resolved状态和rejected状态的回调函数 promise.then(function(value) { // success }, function(error) { // failure });
then方法可以接受两个回调函数作为参数,第一个回调函数是promise对象的状态变成resolved时调用,第二个回调函数是promise对象的状态变成rejected时调用,第二个函数是可选的,不一定提供。这两个函数都接受promise对象传出的值作为参数。
function timeout(ms){ return new Promise((resolve,reject)=>{ setTimeout(resolve,ms,'done'); }); } timeout(100).then((value)=>{ console.log(value); });
promise新建后就会立即执行
let promise = new Promise(function(resolve,reject){ console.log('Promise'); resolve(); }); promise.then(function(){ console.log('resolved.'); }); console.log('Hi!');
代码执行后,输出顺序如下:
Promise
Hi!
resolved.
异步加载图片的例子
function loadImageAsync(url){
return new Promise(function(resolve,reject){
const image = new Image();
image.onload = function(){
resolve(image);
};
image.onerror = functioin(){
reject(new Error('Could not load image at'+url));
};
image.src = url;
});
}
以上代码,使用Promise包装了一个图片加载的异步操作。如果加载成功,就调用resolve方法,否则就调用reject方法。
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.ststusText));
}
};
cosnt client = new XMLHttpRquest();
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.log('出错了',error);
});
getJSON是对XMLHttpRequest对象的封装,用于发出一个针对JSON数据的HTTP请求,并且返回一个promise对象。
一般来说,调用resolve或reject以后,promise的使命就完成了,后续操作应该写在then方法里面,而不是直接写在resolve或reject的后面。所以最好在它们前面加上return语句,这样就不会有意外
new Promise((resolve,reject)=>{
return resolve(1);
//后面的语句不会执行
console.log(2);
});
-
状态
三种状态:pending(进行中)、fufilled(已成功)、rejected(已失败)
只能从第一种状态到第二或第三种状态,状态一旦改变,就不会再变了
-
常用方法
- Promise.all
Promise.all方法用于将多个promise实例,包装成一个新的Promise实例。
const p = Promise.all([p1,p2,p3]);
p的状态由
p1
、p2
、p3
决定,任意一个被rejected,p
的状态就会变成rejected,否则会变成fullfilled状态。- Promise.race
Promise.race方法用于将多个promise实例,包装成一个新的Promise实例。
const p = Promise.race([p1,p2,p3]);
只要
p1
、p2
、p3
之中有一个实例率先改变状态,p
的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p
的回调函数。-
promise和generator的结合
function getFoo(){ return new Promise(function(resolve,reject){ resolve('foo'); }); } const g = function* (){ try{ const foo = yield getFoo(); console.log(foo); } catch (e){ console.log(e); } } function run (generator){ const it = generator(); function go(result){ if(result.done) return result.value; return result.value.then(function(value){ return go(it.next(value)); },function(error){ return go(it.throw(error)); }); } go(it.next()); } run(g);
以上代码的generator函数g
之中,有一个异步操作getFoo
,它返回的就是一个promise
对象。函数run
用来处理这个promise
对象,并调用下一个next
方法