1. 程式人生 > >將已經存在的非同步請求callback轉換為同步promise

將已經存在的非同步請求callback轉換為同步promise

由於js是單執行緒執行,為防止阻塞,會有很多非同步回撥函式callback,巢狀層次多了,可讀性就差了很多。隨著社群的發展,出現了promise。我們來將一些常見的回撥函式做修改,變成promise的鏈式呼叫,簡潔,清晰明瞭。

先理解一點點概念。

每個promise都有三個狀態。pending、Fulfilled、Rejected。最初為pending,狀態一但改變為Fulfilled、Rejected中的一種,即成永遠,不再改變。

pending: 等待狀態。

Fulfilled: 表示成功完成。

Rejected: 表示被拒絕,失敗。

原生的ajax請求


/**
 * 原生請求
 */
function nativeRequest(url) {
  var xhr = new XMLHttpRequest()
  // 這裡我建議的書寫順序是: onreadystatechange -> open -> send
  // 這樣,onreadystatechange 可以獲取 readyState 的狀態 1 2 3 4
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) { // 請求已完成,且響應已就緒
      if (xhr.status === 200) {
        // TODO: 處理返回正常的資料 xhr.responseText
      } else {
        // TODO: 處理返回非正常的資料
      }
    }
  }
  xhr.open('GET', url, true)
  xhr.send(null)
}

promise 風格的請求

/**
 * promisify request
 * 返回promise物件 
 */
function promiseRequest(url) {
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest()
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          resolve(xhr.responseText)
        } else {
          reject(xhr.responseText)
        }
      }
    }
    xhr.open('GET', xhr, true)
    xhr.send(null)
  }).catch(err => {
    console.log(err)
  })
}

jquery中的ajax請求

這裡只使用ajax請求中的get請求,使用常見的幾個引數。


/**
 * ajax get請求
 */
function ajaxResponse(url) {
  $.ajax({
    url: url,
    type: 'GET',
    success: res => {
      console.log(res)
    },
    error: err => {
      console.log(err)
    }
  })
}

轉換為promise風格

/**
 * promise風格的ajax get請求
 * 返回promise物件 
 * 這裡同時用到了es6中的解構賦值預設值和函式引數預設值
 */
function promiseAjaxResponse(url, {
    type = 'GET',
    } = {}) {
  return new Promise((resolve, reject) => {
    $.ajax({
      url,
      type,
      success: res => {
        resolve(res)
      },
      error: err => {
        reject(err)
      }
    })
  })
}

node風格的callback請求


nodeGet(param, function (err, data) { })

TO:


function nodeGetAysnc(param) {

  return new Promise((resolve, reject) => {

    nodeGet(param, function (err, data) {

      if (err !== null) return reject(err)

      resolve(data)

    })

  })

}

DOM load事件 或者其他一次性事件


function load() {

  console.log('onload - end')

}

window.onload = load

TO promise


function promiseLoad() {

  return new Promise(function (resolve, reject) {

    window.onload = resolve

  })

}

promiseLoad().then(load)

參考