1. promise的出现
promise 是 commonJS下的一个规范 , 规范的就是JS中的异步操作方式
thenjs whenjs deferred(jq) , 基于promise开发出的实际代码
es 6 - > ecmaScript 6中已经加入原生JS实现了promise*
首先看一个小栗子
setTimeout(function(){
alert(1);
},1000);
alert(2);
上面呢先出现2,后出现1;因为计时器是异步的,不影响后续执行。假如我们希望按照顺序去操作的话,promise就可以帮助我们实现。
当然我们首先看看用一般的方法怎么实现让它按照顺序执行,下面使用回调方式操作。
function show(time,fn){
setTimeout(function(){
console.log(time+'秒后:');
fn();
},time*1000);
}
show(1,function(){
console.log('操作1');
});
试想,如果我们希望一秒后执行操作1,二秒后执行操作2,三秒后执行操作3,我们可以用下面的代码去写。
function show(time,fn){
setTimeout(function(){
console.log(time+'秒后:');
fn();
},time*1000);
}
show(1,function(){
console.log('操作1');
show(2,function(){
console.log('操作2');
show(3,function(){
console.log('操作3');
});
});
});
但是呢,我们分析上面的代码,不好维护,所以呢,就出现了promise。下来我们正式介绍promise。
2. promise的介绍
- 状态 pending(等待) -> resolve(成功) reject(拒绝)
状态一旦改变就不能再继续变化- then方法 : 调用 resolve reject 状态所对应的回调函数
现在尝试使用promise改写以上代码
function show(time){
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
console.log(time+'秒后:');
resolve(); //①
},time*1000);
});
return promise;
}
show(1).then(function(){
console.log('操作1');
},function(){
console.log('失败');
});
上面代码会在一秒后打印操作1,如果将①换成reject( ),则会在一秒后打印失败。
现在使用promise解决上面层层嵌套的问题
show(1).then(function(){
console.log('操作1');
return show(2);
})
.then(function(){
console.log('操作2');
return show(3);
})
.then(function(){
console.log('操作3');
});
3. promise应用场景
首先看一个栗子,异步操作ajax。以下是一个典型的promise应用场景,结构非常清晰明了。
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
3. promise的辅助方法
首先把上面的代码拿下来
function show(time){
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
console.log(time+'秒后:');
reject();
},time*1000);
});
return promise;
}
show(1).then(function(){
console.log('成功');
}).catch(function(){
console.log('失败');
});
Promise.all
看下面的例子
function p1(){
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
console.log('1秒后:');
resolve();
},1000);
});
return promise;
}
function p2(){
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
console.log('2秒后:');
reject();
},2000);
});
return promise;
}
function p3(){
var promise = new Promise(function(resolve,reject){
setTimeout(function(){
console.log('3秒后:');
resolve();
},3000);
});
return promise;
}
//要想等上面三个都是成功的时候触发,可以这样做
var p = Promise.all([p1(),p2(),p3()]);
p.then(function(){
console.log('都成功的状态才会触发');
},function(){
console.log('只要有一个失败的就会走');
});
Promise.race
p.then(function(){
console.log('只要有一个成功的状态就会触发');
},function(){
console.log('只要有一个失败的就会走');
})
4. 和JQ结合使用
在Jq中promise使用Deferred()来实现的,举例如下
function show(time){
var dfd = $.Deferred();
setTimeout(function(){
console.log(time+'秒后:');
dfd.reject();
},time*1000);
return dfd;
}
show(1).then(function(){
console.log('成功');
},function(){
console.log('失败');
});
done和fail
show(1).done(function(){
console.log('成功');
}).fail(function(){
console.log('失败');
});
when类似于promise.all
function show1(){
var dfd = $.Deferred();
setTimeout(function(){
console.log('第一个');
dfd.resolve();
},2000);
return dfd;
}
function show2(){
var dfd = $.Deferred();
setTimeout(function(){
console.log('第二个');
dfd.resolve();
},5000);
return dfd;
}
$.when(show1(),show2()).then(function(){
console.log('都成功才触发');
});