Promise 與 Confirm 提示框

zy_deng發表於2017-11-29

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 提示框

上圖是一個十分簡單的 Confirm 提示框。其實,我們可以發現 Confirm 提示框也具有 3 種狀態,跟 Promise 三種狀態非常相像。提示框在建立時對應 pending ,點選取消之後對應 rejected ,點選確定之後對應 fulfilled。所以我們可以編寫一個名 為 confirm 的函式 ,這個函式實現兩個功能:

  1. 在建立 Confirm 元件之後,返回一個 Promise。
  2. 當使用者點選確定或者取消按鈕時改變這個 Promise 例項的狀態。

那麼就可以在呼叫 confirm 函式之後的 then 與 catch 中針對不同的操作做出相應的處理。
下面的偽碼描述了這個過程。

confirm().then(() => {
    // 點選了 確定
}).catch(() => {
    // 點選了 取消
})複製程式碼

按照這個思路,我們來一步步實現這個 confirm 函式。

3.1 Confirm 元件

Confirm 元件類似於一個彈出層,其中的內容區域需要居中顯示。使用 fixed 絕對定位 與 flex 佈局可以實現。完整的程式碼點選這裡

3.2 confirm 函式

實現的 confirm 的一些要點:

  1. 呼叫 confirm 函式,建立 Confrim 元件並同時返回一個 Promise 物件。
  2. 在按鈕點選之後,改變 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 是一個非常好的工具。希望大家能掌握它的用法。

參考資料

相關文章