摘要:臆想的針對讀取到的內(nèi)容進(jìn)行操作,比如打印文件內(nèi)容臆想中,讀取文件是有返回值的,將返回值,即文件內(nèi)容,賦給一個變量,然后決定對讀取到的內(nèi)容進(jìn)行相應(yīng)的操作,例如打印文件中的內(nèi)容。
臆想的
let fs = require("fs") function readFile(filename){ ... } let content = readFile("config.js") // 針對讀取到的內(nèi)容進(jìn)行操作,比如打印文件內(nèi)容 console.log(content)
臆想中,讀取文件是有返回值的,將返回值,即文件內(nèi)容,賦給一個變量,然后決定對讀取到的內(nèi)容進(jìn)行相應(yīng)的操作,例如打印文件中的內(nèi)容。
簡而言之,臆想中,讀取文件,打印文件是相互分開的。
回調(diào)let fs = require("fs") function readFile(filename, callback){ fs.readFile(filename, "utf8", (err, data) => { if(err){ throw new err } callback(data) }) } readFile("config.js", data => { console.log(data) })
實際上,在經(jīng)常使用的回調(diào)中,讀取文件和針對文件內(nèi)容相應(yīng)的操作是在一起的,
你在要求讀取文件的同時,還要說明獲取文件內(nèi)容后干嘛
這和習(xí)慣性思維,你先把文件內(nèi)容給我,至于我怎么處理,稍后再說
Promiselet fs = require("fs") function readFile(filename) { return new Promise(function (resolve) { // 這里的callback,是在run函數(shù)中傳遞的 fs.readFile(filename, "utf8", (err, data) => { if (err) { reject(err) } resolve(data) }) }) } let content = readFile("config.js") content.then(res => { console.log(res) }) // 對比臆想中的 let content = readFile("config.js") // 針對讀取到的內(nèi)容進(jìn)行操作,比如打印文件內(nèi)容 console.log(content)
使用Promise后,整個書寫邏輯開始和臆想中的很接近了,讀取文件和對文件內(nèi)容的操作分開了
即通過使用Promise,可以將異步的操作和對異步結(jié)果的處理,分開
來實現(xiàn)一個簡陋的假的Promiselet fs = require("fs") function resolve(value) { let _self = this setTimeout(function () { _self.callbacks.forEach(function (callback) { callback(value); }) }, 0) // 保證在resolve執(zhí)行之前,then方法都已經(jīng)注冊 } class FakePromise { constructor(fn) { // fn是個函數(shù),里面包含異步,異步成功 // Promise在new的過程中就已經(jīng)開始執(zhí)行異步代碼 // 異步代碼執(zhí)行完觸發(fā)resolve,resolve作為異步代碼的參數(shù),它早已經(jīng)實現(xiàn)好 this.value = null this.callbacks = [] fn(resolve.bind(this)) } then(onFulfilled) { this.callbacks.push(onFulfilled) return this } } function readFile(filename) { return new FakePromise(function (resolve) { fs.readFile(filename, "utf8", (err, data) => { if (err) { return } resolve(data) }) }) } let content = readFile("config.js") content.then(res => { console.log(res) })
這樣看來,Promise和發(fā)布-訂閱模式有些相像。promise內(nèi)部也有個事件隊列,通過then注冊事件,通過resolve觸發(fā)。每個promise在創(chuàng)建的時候,就開始執(zhí)行傳遞給它的函數(shù),函數(shù)中會觸發(fā)resolve,這個resolve就是去執(zhí)行所有注冊的事件。
當(dāng)然,實際上promise比這強大的多,首先resolve執(zhí)行所有注冊的事件會保證滯后執(zhí)行,避免還沒通過then注冊完事件,resolve就執(zhí)行了
其次,在異步操作成功之后,通過then注冊事件,可以立馬執(zhí)行,這就需要給promise添加狀態(tài)機制
... then(onFulfilled) { if (this.state === "pending") { this.callbacks.push(onFulfilled) return this } onFulfilled(value) return this } ...
判斷不是"pending",就立刻執(zhí)行注冊的函數(shù)
另外就是每個then()方法,都會返回一個新的promise
大概長這樣
then(onFulfilled) { return new Promise(...) }參考資料
30分鐘,讓你徹底明白Promise原理
生成器let fs = require("fs") function run(taskDef){ // 傳入的taskDef是個生成器函數(shù),執(zhí)行后返回迭代器 let task = taskDef() // 調(diào)用迭代器的next()方法,開始taskDef函數(shù)中的代碼,直至遇到y(tǒng)ield,并將yield的值賦予result let result = task.next() function step(){ if(!result.done){ if(typeof result.value === "function"){ result.value((err, data)=>{ if(err){ result = task.throw(err) return } result = task.next(data) step() }) // 這里的result.value(...){...} // 調(diào)用的是function(callback){fs.readFile(filename, "utf8", callback)} }else{ result = task.next(data) step() // 判斷任務(wù)是否執(zhí)行完 } } } step() // task.next(data) 繼續(xù)執(zhí)行生成器中的代碼,并將值傳回給觸發(fā)這次next()的yield的等號左邊的變量 } function readFile(filename){ return function (callback){ // 這里的callback,是在run函數(shù)中傳遞的 fs.readFile(filename, "utf8", callback) } } run(function*(){ let content = yield readFile("config.js") // 傳遞函數(shù)至run函數(shù)中,并由run傳遞參數(shù)調(diào)用 // 對文件內(nèi)容進(jìn)行處理 console.log(content) }) // 對比臆想中的 let content = readFile("config.js") // 針對讀取到的內(nèi)容進(jìn)行操作,比如打印文件內(nèi)容 console.log(content)
生成器函數(shù)可以停止函數(shù)執(zhí)行,代碼在yield readFile("copy.js")處暫停
異步任務(wù)的回調(diào)中調(diào)用迭代器的next()方法,使生成器函數(shù)中的代碼繼續(xù)執(zhí)行,并通過next()方法傳遞參數(shù)回至生成器函數(shù)中,異步任務(wù)完成,返回值已經(jīng)賦值給了content
Promise+generatorlet fs = require("fs") function run(taskDef){ // 傳入的taskDef是個生成器函數(shù),執(zhí)行后返回迭代器 let task = taskDef() // 調(diào)用迭代器的next()方法,開始taskDef函數(shù)中的代碼,直至遇到y(tǒng)ield,并將yield的值賦予result let result = task.next() function step(){ if(!result.done){ let promise = Promise.resolve(result.value) promise.then(value => { result = task.next(value) step() }).catch(err => { result = task.throw(err) step() }) } } step() // task.next(data) 繼續(xù)執(zhí)行生成器中的代碼,并將值傳回給觸發(fā)這次next()的yield的等號左邊的變量 } function readFile(filename){ return new Promise(function (resolve, reject){ // 這里的callback,是在run函數(shù)中傳遞的 fs.readFile(filename, "utf8", (err, data) => { if(err){ reject(err) } resolve(data) }) }) } run(function*(){ let content = yield readFile("config.js") // 傳遞函數(shù)至run函數(shù)中,并由run傳遞參數(shù)調(diào)用 // 對文件內(nèi)容進(jìn)行處理 console.log(content) }) console.log("先執(zhí)行")Async&await
是不是和promise+generator很像
let fs = require("fs") function readFile(filename) { return new Promise(function (resolve) { // 這里的callback,是在run函數(shù)中傳遞的 fs.readFile(filename, "utf8", (err, data) => { if (err) { reject(err) } resolve(data) }) }) } (async function test() { let content = await readFile("copy.js") console.log(content) })()參考資料
深入理解ES6
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/92595.html
摘要:但是往往越簡單的東西越容易讓我們忽視,從而導(dǎo)致一些不該有的發(fā)生,作為一名嚴(yán)謹(jǐn)?shù)某绦騿T,怎么能讓這種事情發(fā)生呢所以下面我們就來了解一下關(guān)于日志的那些正確使用姿勢。級別表示出現(xiàn)了嚴(yán)重錯誤,程序?qū)袛鄨?zhí)行。 前言 關(guān)于日志,在大家的印象中都是比較簡單的,只須引入了相關(guān)依賴包,剩下的事情就是在項目中盡情的打印我們需要的信息了。但是往往越簡單的東西越容易讓我們忽視,從而導(dǎo)致一些不該有的bug發(fā)...
摘要:方法區(qū)溢出在的方法區(qū)中,它主要存放了類的信息,常量,靜態(tài)變量等。運行結(jié)果簡單解決思路一般來說此類問題多出現(xiàn)在存在遞歸的地方,要從代碼里重新審視遞歸未結(jié)束的原因,若遞歸的方法沒問題可以根據(jù)實際情況調(diào)整參數(shù)的大小。 前言 如今不管是在面試還是在我們的工作中,OOM總是不斷的出現(xiàn)在我們的視野中,所以我們有必要去了解一下導(dǎo)致OOM的原因以及一些基本的調(diào)整方法,大家可以通過下面的事例來了解一下什...
摘要:子組件向父組件通信方法一使用事件父組件向子組件傳遞事件方法,子組件通過觸發(fā)事件,回調(diào)給父組件。非父子組件兄弟組件之間的數(shù)據(jù)傳遞非父子組件通信,官方推薦使用一個實例作為中央事件總線。 寫在前面 因為對Vue.js很感興趣,而且平時工作的技術(shù)棧也是Vue.js,這幾個月花了些時間研究學(xué)習(xí)了一下Vue.js源碼,并做了總結(jié)與輸出。 文章的原地址:https://github.com/answ...
摘要:雖然這個模式運行效果很不錯,但是如果嵌套了太多的回調(diào)函數(shù),就會陷入回調(diào)地獄。當(dāng)需要跟蹤多個回調(diào)函數(shù)的時候,回調(diào)函數(shù)的局限性就體現(xiàn)出來了,非常好的改進(jìn)了這些情況。 JavaScript引擎是基于單線程 (Single-threaded) 事件循環(huán)的概念構(gòu)建的,同一時刻只允許一個代碼塊在執(zhí)行,所以需要跟蹤即將運行的代碼,那些代碼被放在一個任務(wù)隊列 (job queue) 中,每當(dāng)一段代碼準(zhǔn)...
閱讀 5160·2023-04-25 19:30
閱讀 2187·2023-04-25 15:09
閱讀 2634·2021-11-16 11:45
閱讀 2193·2021-11-15 18:07
閱讀 1473·2021-11-11 17:22
閱讀 2133·2021-11-04 16:06
閱讀 3589·2021-10-20 13:47
閱讀 3051·2021-09-22 16:03