描述
Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。
一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知的值。它让您能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。 这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
一个 Promise 必然处于以下几种状态之一:
- 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
- 已兑现(fulfilled): 意味着操作成功完成。
- 已拒绝(rejected): 意味着操作失败。
下图便是promise的链式操作工作图
jQuery的deferred对象详解
简述
该对象是为了避免如ajax或者大数据操作数组等情况时出现结果不能立即返回而应运而生的对象,该对象的作用是通过将当前为当前需要一段时间的操作指定一个回调方法,保证js代码可以去处理其他的代码,当该代码端完成后,就将其存入任务队列中,通过回调方法进行结果处理。
关于任务队列的概念,可以参考笔者这篇文章
关于js中同步和异步的理解
错误示例
var dtd = $.Deferred(); // 新建一个Deferred对象
var wait = function(dtd){
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变Deferred对象的执行状态
};
setTimeout(tasks,5000);
return dtd;
};
$.when(wait(dtd))
.done(function(){
alert("哈哈,成功了!"); })
.fail(function(){
alert("出错啦!"); });
dtd.resolve(); //以为when是一条异步链,在执行期间这条代码提前将dtd设置为已完成状态,导致输出顺序为 哈哈,成功了!->执行完毕!
正确示例
为了保证deferred
状态不被外界修改,我们只需将保证条链的resolve和reject方法不能被外界调用即可,即将return dtd改为return dtd.promise();
var dtd = $.Deferred(); // 新建一个Deferred对象
var wait = function(dtd){
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变Deferred对象的执行状态为已完成
};
setTimeout(tasks,5000);
return dtd.promise(); // 返回promise对象,这条语句相当于将dtd绑定到一个对象上,对外隐藏了resolve和reject操作
};
var d = wait(dtd); // 新建一个d对象,改为对这个对象进行操作
$.when(d)
.done(function(){
alert("哈哈,成功了!"); })
.fail(function(){
alert("出错啦!"); });
d.resolve(); // 此时,这个语句是无效的,以为dtd被封装到promise对象中了,隐藏了resolve和reject
promise用法示例
可以看出在每个promise中,每个promise的异步,但在整条链下代码执行确是同步的,所以promise适用于处理大量需要同步执行异步任务的代码中。
<script>
//做饭
function cook() {
var p = new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log('做饭完毕!');
resolve('鸡蛋炒饭');
}, 0);
console.log('开始做饭。');
});
return p;
}
//吃饭
function eat(data) {
var p = new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log('吃饭完毕!');
resolve('一块碗和一双筷子');
}, 0);
console.log('开始吃饭:' + data);
});
return p;
}
function wash(data) {
console.log('开始洗碗:' + data);
var p = new Promise(function (resolve, reject) {
//做一些异步操作
setTimeout(function () {
console.log('洗碗完毕!');
resolve('干净的碗筷');
}, 2000);
});
return p;
}
cook()
.then(function (data) {
return eat(data);
})
.then(function (data) {
return wash(data);
})
.then(function (data) {
console.log(data);
});
</script>