JavaScript-promise

問題需求

封裝讀取文件的方法(讀取文件爲異步操做),不用es6javascript

// 需求:你要封裝一個方法,我給你一個要讀取文件的路徑,你這個方法能幫我讀取文件,並把內容返回給我

const fs = require('fs')
const path = require('path')

// 這是普通讀取文件的方式
/* fs.readFile(path.join(__dirname, './files/1.txt'), 'utf-8', (err, dataStr) => {
  if (err) throw err
  console.log(dataStr)
}) */

// 初衷: 給定文件路徑,返回讀取到的內容
// 咱們能夠規定一下, callback 中,有兩個參數,第一個參數,是 失敗的結果;第二個參數是成功的結果;
// 同時,咱們規定了: 若是成功後,返回的結果,應該位於 callback 參數的第二個位置,此時, 第一個位置 因爲沒有出錯,因此,放一個 null;  若是失敗了,則 第一個位置放 Error對象,第二個位置防止一個 undefined
function getFileByPath(fpath, callback) {
  fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    // 若是報錯了,進入if分支後,if後面的代碼就沒有必要執行了
    if (err) return callback(err)
    // console.log(dataStr)
    // return dataStr
    callback(null, dataStr)
  })
}

/* var result = getFileByPath(path.join(__dirname, './files/1.txt'))
console.log(result) */
getFileByPath(path.join(__dirname, './files/1.txt'), (err, dataStr) => {
  // console.log(dataStr + '-----')
  if (err) return console.log(err.message)
  console.log(dataStr)
})

回調地獄

對上面代碼進行改進html

// 需求:你要封裝一個方法,我給你一個要讀取文件的路徑,你這個方法能幫我讀取文件,並把內容返回給我

const fs = require('fs')
const path = require('path')


function getFileByPath(fpath, succCb, errCb) {
  fs.readFile(fpath, 'utf-8', (err, dataStr) => {
    if (err) return errCb(err)
    succCb(dataStr)
  })
}

// getFileByPath(path.join(__dirname, './files/11.txt'), function (data) {
//   console.log(data + '娃哈哈,成功了!!!')
// }, function (err) {
//   console.log('失敗的結果,咱們使用失敗的回調處理了一下:' + err.message)
// })

// 需求: 先讀取文件1,再讀取文件2,最後再讀取文件3
// 回調地獄
// 使用 ES6 中的 Promise,來解決 回調地獄的問題;
// 問: Promise 的本質是要幹什麼的:就是單純的爲了解決回調地獄問題;並不能幫咱們減小代碼量;
getFileByPath(path.join(__dirname, './files/1.txt'), function (data) {
  console.log(data)

  getFileByPath(path.join(__dirname, './files/2.txt'), function (data) {
    console.log(data)

    getFileByPath(path.join(__dirname, './files/3.txt'), function (data) {
      console.log(data)
    })
  })
})

promise概念

  1. Promise 是一個 構造函數,既然是構造函數, 那麼,咱們就能夠 new Promise() 獲得一個 Promise 的實例;
  2. 在 Promise 上,有兩個函數,分別叫作 resolve(成功以後的回調函數) 和 reject(失敗以後的回調函數)
  3. 在 Promise 構造函數的 Prototype 屬性上,有一個 .then() 方法,也就說,只要是 Promise 構造函數建立的實例,均可以訪問到 .then() 方法
  4. Promise 表示一個 異步操做;每當咱們 new 一個 Promise 的實例,這個實例,就表示一個具體的異步操做;
  5. 既然 Promise 建立的實例,是一個異步操做,那麼,這個 異步操做的結果,只能有兩種狀態:
    5.1 狀態1: 異步執行成功了,須要在內部調用 成功的回調函數 resolve 把結果返回給調用者;
    5.2 狀態2: 異步執行失敗了,須要在內部調用 失敗的回調函數 reject 把結果返回給調用者;
    5.3 因爲 Promise 的實例,是一個異步操做,因此,內部拿到 操做的結果後,沒法使用 return 把操做的結果返回給調用者; 這時候,只能使用回調函數的形式,來把 成功 或 失敗的結果,返回給調用者;
  6. 咱們能夠在 new 出來的 Promise 實例上,調用 .then() 方法,【預先】 爲 這個 Promise 異步操做,指定 成功(resolve) 和 失敗(reject) 回調函數;

注意:這裏 new 出來的 promise, 只是表明 【形式上】的一個異步操做;
什麼是形式上的異步操做:就是說,咱們只知道它是一個異步操做,可是作什麼具體的異步事情,目前還不清楚
var promise = new Promise()java

const fs = require('fs')

// 每當 new 一個 Promise 實例的時候,就會當即 執行這個 異步操做中的代碼
// 也就是說,new 的時候,除了可以獲得 一個 promise 實例以外,還會當即調用 咱們爲 Promise 構造函數傳遞的那個 function,執行這個 function 中的 異步操做代碼;
/* var promise = new Promise(function () {
  fs.readFile('./files/2.txt', 'utf-8', (err, dataStr) => {
    if (err) throw err
    console.log(dataStr)
  })
}) */


// 初衷: 給路徑,返回讀取到的內容
function getFileByPath(fpath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {

      if (err) return reject(err)
      resolve(dataStr)

    })
  })
}

使用promise解決回調地獄

兩種狀況:node

會中斷

const fs = require('fs')

function getFileByPath(fpath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {

      if (err) return reject(err)
      resolve(dataStr)

    })
  })
}

// 讀取文件1
// 在上一個 .then 中,返回一個新的 promise 實例,能夠繼續用下一個 .then 來處理


// 若是 ,前面的 Promise 執行失敗,咱們不想讓後續的Promise 操做被終止,能夠爲 每一個 promise 指定 失敗的回調
 getFileByPath('./files/11.txt')
  .then(function (data) {
    console.log(data)

    // 讀取文件2
    return getFileByPath('./files/2.txt')
  }, function (err) {
    console.log('這是失敗的結果:' + err.message)
    // return 一個 新的 Promise
    return getFileByPath('./files/2.txt')
  })
  .then(function (data) {
    console.log(data)

    return getFileByPath('./files/3.txt')
  })
  .then(function (data) {
    console.log(data)
  }).then(function (data) {
    console.log(data)
  })

不會中斷

const fs = require('fs')

function getFileByPath(fpath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {

      if (err) return reject(err)
      resolve(dataStr)

    })
  })
}

// 當 咱們有這樣的需求: 哪怕前面的 Promise 執行失敗了,可是,不要影響後續 promise 的正常執行,此時,咱們能夠單獨爲 每一個 promise,經過 .then 指定一下失敗的回調;

// 有時候,咱們有這樣的需求,個上面的需求恰好相反:若是 後續的Promise 執行,依賴於 前面 Promise 執行的結果,若是前面的失敗了,則後面的就沒有繼續執行下去的意義了,此時,咱們想要實現,一旦有報錯,則當即終止全部 Promise的執行;

getFileByPath('./files/1.txt')
  .then(function (data) {
    console.log(data)

    // 讀取文件2
    return getFileByPath('./files/22.txt')
  })
  .then(function (data) {
    console.log(data)

    return getFileByPath('./files/3.txt')
  })
  .then(function (data) {
    console.log(data)
  })
  .catch(function (err) { // catch 的做用: 若是前面有任何的 Promise 執行失敗,則當即終止全部 promise 的執行,並 立刻進入 catch 去處理 Promise中 拋出的異常;
    console.log('這是本身的處理方式:' + err.message)
  })

jquery中使用promise

想不到jQuery這個強大的庫中居然支持promise,果真強大jquery

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>

  <input type="button" value="获�数�" id="btn">

  <script src="./node_modules/jquery/dist/jquery.min.js"></script>

  <script>
    $(function () {
      $('#btn').on('click', function () {
        $.ajax({
          url: './data.json',
          type: 'get',
          dataType: 'json'
        })
          .then(function (data) {
            console.log(data)
          })
      })
    });
  </script>
</body>

</html>
{
  "name": "小強",
  "age": 18
}
相關文章
相關標籤/搜索