/*
Promise 含义:
Promise 是异步编程的一种解决方案,比传统解决方案 ———— 回调函数和事件 ———— 更合理且更强大。
它最早由社区提出并实现,es6 将其写进了语言标准,统一了用法,并原生提供了 Promise 对象。
所谓 Promise,简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上来说,Promise 是一个对象,从可以获取异步操作的消息。
Promise 提供统一的 Api ,各种异步操作都可以用同样的方法处理。
*/
/*
Promise 对象有以下两个特点:
1. 对象的状态不受外界影响。Promise 对象代表一个异步操作,有 3 种状态:Pending(进行中)、Fulfilled(已成功)、和 Rejected(已失败)
只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2. 一旦状态改变就不会再变,任何时候都可以得到这个结果。
Promise 对象的状态改变只有两种可能:从 Pending 变为 Fulfilled 和 从 Pending 变为 Rejected。
只要这两种情况发生,状态就凝固了,不会再变,而是一直保持这个结果,这时就称为 Resolved(已定型)。
就算改变已经发生,再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同。事件的特点是:如果错过了它,再去监听是得不到结果的。
(注意:一般 Resolved 统一指 Fulfilled 状态,不包含 Rejected状态)
*/
/*
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数,此外,Promise 提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点:
首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise 内部抛出得错误不会反应到外部。
再者,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
如果某些事件不断地反复发生,一般来说,使用 Stream 模式是比部署 Promise 更好的选择。
*/
/*
Promise 基本用法:
es6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例
*/
// 下面的代码创造了一个 Promise 实例
var promise1 = new Promise(function(resolve, reject) {
// ...some code
if ( true ) { // 异步操作成功
resolve(value)
} else { // 异步操作失败
reject(error)
}
})
/*
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject ,它们是两个函数,由 javascript 引擎提供,不要自己部署
resolve 函数的作用是,将 Promise 对象的状态从 “未完成” 变为 “成功” (即从 Pending 变为 Resolved),在异步操作成功时调用,并将异步操作的结果作为参数传递出去;
reject 函数的作用是:将 Promise 对象的状态从 “未完成” 变为 “”失败 (即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去
*/
// Promise 实例生成之后,可以用 then 方法分别指定 Resolved 状态 和 Rejected 状态的回调函数
promise1.then(function(value) {
// success
}, function(error) {
// failure
})
/*
then 方法可以接受两个回调函数作为参数。
第一个回调函数是 Promise 对象的状态变为 Resolved 时调用,第二个回调函数是 Promise 对象的状态变为 Rejected 时调用。
其中,第二个参数是可选的。
这两个函数都接受 Promise 对象传出的值作为参数
*/
// 下面是一个 Promise 对象的简单例子:
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done')
})
}
timeout(100).then((value) => {
console.log(value) // 100ms 后打印 done
})
// 上面的代码中,timeout 方法返回一个 Promise 实例,表示一段时间以后才会发生的结果,过了指定的时间(ms参数)以后,Promise实例的状态变为 Resolved,就会触发 then 方法绑定的回调函数
// Promise 函数新建后就会立即执行
let promise2 = new Promise(function(resolve, reject) {
console.log('Promise')
resolve()
})
promise2.then(function() {
console.log('Resolved')
})
console.log('Hi!')
// Promise
// Hi!
// Resolved
// 上面的代码中,Promise 新建后会立即执行,所以首先输出的是 Promise 。
// ****然后,then 方法指定的回调函数将在当前脚本所有同步任务完成后才会执行,所以 Resolved 最后输出。****
// 下面是异步加载图片的例子:
function loadImgAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image()
image.onload = function() {
resolve(image)
}
image.onerror = function() {
reject(new Error('Could not load image at ' + url))
}
image.src = url
})
}
// 上面的代码中使用 Promise 包装了一个图片加载的异步操作。如果加载成功,就调用 resolve 方法,否则调用 reject 方法
// 下面是一个用 Promise 对象实现的 AJAX 操作的例子:
var getJSON = function(url) {
var promise3 = new Promise(function(resolve, reject) {
var client = new XHLHttpRequest()
client.open('GET', url)
client.onreadystatechange = handler
client.responseType = 'json'
client.setRequestHeader('Accept', 'application/json')
client.send()
function handler() {
if (this.readyState !== 4) {
return
}
if (this.readyState === 200) {
resolve(this.response)
} else {
reject(new Error(this.statusText))
}
}
})
return promise3
}
getJSON('/posts.json').then(function(json) {
console.log('Contents: ' + json)
}, function(error) {
console.log('出错了' , error)
})
// 上面的代码中,getJSON 是对 XMLHttpRequest 对象的封装,用于发出一个针对 JSON 数据的 HTTP 请求,并返回一个 Promise 对象。
// 需要注意的是,在 getJSON 内部,resolve 函数和 reject 函数调用时都带有参数
14.1、Promise
最新推荐文章于 2023-10-14 22:28:02 发布