[20190512]
异步编程的一种解决方案。
对比对象:回调函数和事件。
对比结果:更合理更强大。
简单说,就是容器。里面保存着某个未来才会结束的事件。通常是异步操作。
Promise是一个对象,从它上面可以获得异步操作的消息。统一的API,各种异步操作都可以用同样的方法进行处理。
Promise对象的两大特点
- 对象的状态不受外界影响
- 状态一旦改变,就不会再变
Promise对象代表一个异步操作。有三种状态:
-
pending
进行中 -
fulfilled
已成功 -
rejected
已失败
只有异步操作的结果才可以决定当前是哪种状态。其他操作都无法改变这个状态,即承诺,其他手段无法改变。
Promise状态改变的两种可能:
-
pending
-->fulfilled
-
pending
-->rejected
单向数据流,一旦这两种状况之一发生,状态就凝固了,不会再变了,会一直保持这个结果,此时就成为resolved(已定型)
。
注意:如果改变已经发生,再对Promise对象添加回调函数,也会立即得到这个结果。
和事件的区别是,一旦事件错过了,再去监听是得不到结果的。
优点
有了Promise
,就可以将异步操作以同步操作的流程表达出来,避免层层回调函数。
Promise对象还提供了统一的接口,使得控制异步操作更加容易了。
缺点
-
无法取消
Promise
,一旦新建它就会立即执行,无法中途取消。 -
如果不设置回调函数,
Promise
内部抛出的错误,不会反应到外部。 -
处于pending状态,无法得知目前进展到哪个阶段
基本使用
下面这个就是基本使用框架:
const promise = new Promise(function(resolve, reject) {
if (/* 异步操作成功 */) {
resolve(value);
} else {
reject(error);
}
});
注意,Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是:
resolve
reject
这也是两个函数,由JavaScript
引擎提供,不用自己部署。
resolve函数:pending --> fulfilled
将Promise
对象的状态从未完成变成成功。
在异步操作成功时调用,并将异步操作的结果作为参数传递出去。
reject函数:pending --> rejected
异步操作失败时调用,将异步操作报出的错误作为参数传递出去。
promise.then分别指定两个状态的回调函数
promise.then(function(value) {
// success
}, function(error) {
// failure
});
需要在生成实例之后使用。第一个函数表示Promise对象变成resolved
时调用,第二个回调函数在状态变为rejected
时调用。
注:第二个函数是可选的。
两个函数的参数都是来自Promise
对象传出的值。
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
})
注意done
会作为resolve
的参数。
Q: resolve
函数到底要干嘛啊??
记住这个框架:异步操作执行完毕后,就调用resolve
函数,否则就调用reject
方法。
Promise实现Ajax
const getJSON = function(url) {
const promise = new Promise((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('/posts.json').then(function(json) {
console.log("Contents: " + json);
}, function(error) {
console.error('出错了', error);
});
http://es6.ruanyifeng.com/#docs/promise
END.
网友评论