問題需求 封裝讀取文件的方法(讀取文件為非同步操作),不用es6 回調地獄 對上面代碼進行改進 promise概念 1. Promise 是一個 構造函數,既然是構造函數, 那麼,我們就可以 new Promise() 得到一個 Promise 的實例; 2. 在 Promise 上,有兩個函數,分別 ...
問題需求
封裝讀取文件的方法(讀取文件為非同步操作),不用es6
// 需求:你要封裝一個方法,我給你一個要讀取文件的路徑,你這個方法能幫我讀取文件,並把內容返回給我
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)
})
回調地獄
對上面代碼進行改進
// 需求:你要封裝一個方法,我給你一個要讀取文件的路徑,你這個方法能幫我讀取文件,並把內容返回給我
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概念
- Promise 是一個 構造函數,既然是構造函數, 那麼,我們就可以 new Promise() 得到一個 Promise 的實例;
- 在 Promise 上,有兩個函數,分別叫做 resolve(成功之後的回調函數) 和 reject(失敗之後的回調函數)
- 在 Promise 構造函數的 Prototype 屬性上,有一個 .then() 方法,也就說,只要是 Promise 構造函數創建的實例,都可以訪問到 .then() 方法
- Promise 表示一個 非同步操作;每當我們 new 一個 Promise 的實例,這個實例,就表示一個具體的非同步操作;
- 既然 Promise 創建的實例,是一個非同步操作,那麼,這個 非同步操作的結果,只能有兩種狀態:
5.1 狀態1: 非同步執行成功了,需要在內部調用 成功的回調函數 resolve 把結果返回給調用者;
5.2 狀態2: 非同步執行失敗了,需要在內部調用 失敗的回調函數 reject 把結果返回給調用者;
5.3 由於 Promise 的實例,是一個非同步操作,所以,內部拿到 操作的結果後,無法使用 return 把操作的結果返回給調用者; 這時候,只能使用回調函數的形式,來把 成功 或 失敗的結果,返回給調用者; - 我們可以在 new 出來的 Promise 實例上,調用 .then() 方法,【預先】 為 這個 Promise 非同步操作,指定 成功(resolve) 和 失敗(reject) 回調函數;
註意:這裡 new 出來的 promise, 只是代表 【形式上】的一個非同步操作;
什麼是形式上的非同步操作:就是說,我們只知道它是一個非同步操作,但是做什麼具體的非同步事情,目前還不清楚
var promise = new Promise()
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解決回調地獄
兩種情況:
會中斷
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,果然強大
<!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
}