Promise 是 ES6 中非常重要的概念。相较于回调函数和事件监听,Promise 可以更好的解决了异步编程中遇到的问题。
Promise 是 ES6 新引入的对象。使用 Promise 封装一个异步过程,避免了使用回调函数,链式调用让代码更加清晰。
1. Promsie 的基本概念
Promise 对象是个构造函数,通过 new 创建一个 Promise 实例。
const promise = new Promise((resolve, reject) => {})一个 Promise 对象有 3 种状态:
- pending: 初始状态,不是成功或失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
执行 Promise 回调中的 resolve 与 reject 函数改变 Promise 对象的状态。
2. Promsie 的应用
使用 Promise 实现一个简单的 ajax 函数是个非常好的例子。
// 封装 XMLHttpRequest
funtion ajax () {
return new Promise((resolve, reject) => {
var req = new XMLHttpRequest()
req.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE) {
if (this.status === 200) {
resolve(this.responseText)
} else {
reject(new Error('ajax error'))
}
}
}
req.open('GET', '/url')
req.send()
})
}
// 调用
ajax().then(res => {
// ajax 成功之后的 responseText
}).catch(err => {})resolve 与 reject 函数调用时的可以传递参数,在 Promise 实例之后的 then 与 catch 回调中可以获取到这些参数。这样的话,便可以对异步过程传递出的信息做出相对应的处理。
3. Confirm 提示框与 Promsie
上图是一个十分简单的 Confirm 提示框。其实,我们可以发现 Confirm 提示框也具有 3 种状态,跟 Promise 三种状态非常相像。提示框在创建时对应
pending ,点击取消之后对应 rejected ,点击确定之后对应 fulfilled。所以我们可以编写一个名 为 confirm 的函数 ,这个函数实现两个功能:
- 在创建 Confirm 组件之后,返回一个 Promise。
- 当用户点击确定或者取消按钮时改变这个 Promise 实例的状态。
那么就可以在调用 confirm 函数之后的 then 与 catch 中针对不同的操作做出相应的处理。
下面的伪码描述了这个过程。
confirm().then(() => {
// 点击了 确定
}).catch(() => {
// 点击了 取消
})按照这个思路,我们来一步步实现这个 confirm 函数。
3.1 Confirm 组件
Confirm 组件类似于一个弹出层,其中的内容区域需要居中显示。使用 fixed 绝对定位 与 flex 布局可以实现。完整的代码点击这里。
3.2 confirm 函数
实现的 confirm 的一些要点:
- 调用 confirm 函数,创建 Confrim 组件并同时返回一个 Promise 对象。
- 在按钮点击之后,改变 Promise 对象的状态,触发之后 then 或者 catch 执行,同时关闭弹出层,销毁组件。
import Vue from 'vue'
let currentMsg = null
let instance = null
const ConfirmConstructor = Vue.extend(require('./Index.vue'))
function confirm (option = {}) {
instance = new ConfirmConstructor({
el: document.createElement('div')
})
// ...
// 弹出层再次隐藏时时销毁组件
instance.$watch('display', function (val) {
if (!val) {
instance.$destroy(true)
instance.$el.parentNode.removeChild(instance.$el)
}
instance.callBack = defaultCallBack
document.body.appendChild(instance.$el)
// 显示
instance.display = true
return new Promise((resolve, reject) => {
currentMsg = { resolve, reject }
})
})
}
function defaultCallBack (action) {
// ...
if (action === 'confirm') {
currentMsg.resolve('confirm')
} else {
currentMsg.reject('cancel')
}
}
export default confirm在需要的时候,导入 confirm 函数,通过链式调用即可。
完成的代码片段点击这里。
4. 总结
本文简单介绍了一下 Promise 的概念,并且应用 Promise 实现了一个简单的 confirm 函数。从以上例子可以看出,对于一些异步操作, Promise 是一个非常好的工具。希望大家能掌握它的用法。