<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
2022年全國甲卷高考語文作文已然出爐,筆者看到後居然想起了這個表情包
好傢伙,還好我提前成為了一名默默在卷大學生,不然以這篇作文的難度足以讓我招架不住。話不多說,咱們來看看百度作文給出的題目解析:
這是一則材料作文。材料由兩個部分組成,第一部分是現象,介紹傳統文化經典《紅樓夢》中眾人給匾額題名三種不同的方式;第二部分是對上述三種題名方法的評價,暗示了對傳統文化的繼承、發展與創新。“直接移用”,“借鑑化用”,“根據情境獨創”,也就是直接學習、借鑑、創新三步走。在此基礎上,由文學作品中的情節內涵拓展到更廣泛的領域,引發學生深入思考。
透過這個解析我們可以看到這則材料作文由兩個部分構成,第一部分是現象,具體是指《紅樓夢》中眾人給匾額題名三種不同的方式;第二部分則是對上述三種題名方法的評價。由於筆者水平有限,所以決定在直接參照、借鑑化用、根據情境獨創
這三個題眼上下手,那麼它們所對應的順序也自然是學習、借鑑、創新
,通過一步一步的摸索,最終達到好的理想狀況,而又經過對題目解析的反覆揣摩,筆者腦中忽然靈光一現,我能不能以JavaScript中處理並行請求的幾種方式為素材來試著寫寫這篇作文呢?
因筆者水平有限,本篇文章所理解內容僅為個人觀點。我會嘗試將“翼然”、“瀉玉”、“沁芳”分為三個階段,每個階段都是對前一個階段的昇華,通過一步一步的摸索、前進,最終達到“沁芳”的理想層面。
我之前的介紹過關於非同步任務的題目雖然也不少,但究竟應該如何優雅的處理並行請求呢?要知道在ES6
之前,我們傳送依賴請求大概如下所示:
場景:根據使用者id(001),獲取到使用者姓名後,再獲取使用者性別,再獲取使用者年齡
function getUserName(id, callback) { setTimeout(function () { callback('001姓名為鯊魚辣椒') }, 1000) } function getUserSex(id, callback) { setTimeout(function () { callback('001性別為男') }, 1000) } function getUserAge(id, callback) { setTimeout(function () { callback('001年齡為5') }, 1000) } // 開始套娃 getUserName('001', function (name) { console.log(name) getUserSex('001', function (sex) { console.log(sex) getUserAge('001', function (age) { console.log(age) }) }) })
由上述程式碼可知,這種寫法通常會飽受回撥地獄的“折磨”,尤其是當依賴的請求變的越來越多時,我們的“屎山”也便一發不可收拾了。當Promise
問世之後,我們來看看又該如何優化,而這一優化是不是也代表著“翼然”向“瀉玉”所作出的轉變呢?
function getUserName(id) { return new Promise(function (resolve) { setTimeout(function () { resolve('001姓名為鯊魚辣椒') }, 1000) }) } function getUserSex(id) { return new Promise(function (resolve) { setTimeout(function () { resolve('001性別為男') }, 1000) }) } function getUserAge(id) { return new Promise(function (resolve) { setTimeout(function () { resolve('001年齡為5') }, 1000) }) } // 禁止套娃,一切都開始扁平了起來 getUserName('001').then(function (data) { console.log(data) return getUserSex('001') }).then(function (data) { console.log(data) return getUserAge('001') }).then(function (data) { console.log(data) })
由此可見,當應用了Promise
之後,這座“屎山”也隨之被剷平了。如果說then
的鏈式呼叫足以磨平請求程式碼的“屎山”,那麼我們今天用一個需求,來展現async
降維打擊的能力之強,下面我們開始逐漸處理並行請求,也一道解開“翼然”、“瀉玉”、“沁芳”之間的關係
Promise
的特點是同步執行程式碼,且在未決議之前擁有三種狀態:初始化狀態為pending
、成功狀態為resolve
、失敗狀態為rejected
。在未呼叫resolve
以及rejected
之前,狀態始終保持為pending
,呼叫resolve
和rejected
後狀態分別為成功/失敗,要注意的是狀態一旦確定,不可更改。每個Promise物件都會返回一個then
方法,這個then
方法會在Promise
物件成功/失敗時如期呼叫,因為這是Promise
所作出的承諾,例如:
var p = new Promise((resolve, rejected) => { // 1秒鐘之後呼叫resolve,將初始化狀態改為成功狀態 // 注意,在此1秒鐘之前,p的狀態始終為初始化狀態,因為Promise尚未作出決議 setTimeout(resolve, 1000) }) // then方法會在約1秒鐘後執行 p.then(data => console.log(data))
all
方法接收一個具有iterator
介面的資料,例如陣列。要注意的是這個陣列中的每一個成員都必須是一個Promise
物件,all
方法會返回這些Promise
物件成功或失敗的值,例如:
var p = async () => await new Promise(r => setTimeout(r, 1000)) var f = Promise.all([p, p]) // then方法會在約1秒鐘後執行 p().then(data => console.log(data))
async
函數始終會返回一個Promise
物件,這個Promise
物件的狀態取決於async
函數的返回值。await
關鍵字的職責就是非同步求值,通常後面會是一個Promise
物件,await
關鍵字會“自動”幫我們then
這個Promise
物件,然後拿到資料進行返回。注意,只有當await
後面的這個Promise
物件決議了,async
函數才會繼續往下執行,否則交出執行緒轉而執行其它任務,例如:
// f會在約1秒鐘後決議 var f = async () => await new Promise(r => setTimeout(r, 1000)) // then方法會在約1秒鐘後執行 f().then(data => console.log(data))
回顧完成,接下來我們通過這個需求來解開“翼然”、“瀉玉”、“沁芳”之間的關係。比如我有一個裝有一百個書本id
的陣列,我需要獲取每個書本的詳細內容,雖然是一百本書,但由於只有一個介面,所以需要重複呼叫,只不過在呼叫時每次的入參id均不同而已
books中儲存著每個書本的id,我們需要通過這些枯燥無味的id來拿到每個書本所對應的資訊
var books = [ {id: "0000"}, {id: "1111"}, {id: "2222"}, {id: "3333"}, // more... ]
我們先封裝一個request
方法,用於請求單個書本id所對應的資訊。因為沒有這麼合適的介面來供我們練習,所以此處暫時決定使用setTimeout
來代替請求區域
// request方法會在約1秒鐘後「請求成功」 var request = id => new Promise(resolve => setTimeout(resolve, 1000))
通過xhr
封裝一個請求,要注意的是這裡的請求函數requestJs
並未用到Promise
物件,而是使用了原汁原味的回撥模式,因為在ES6
之前Promise
尚未面世,這也正對應了最開始的階段——“翼然”
var info = [] var requestJs = (id, callback) => { var xhr = new XMLHttpRequest() open('GET', 'url') xhr.send(null) xhr.onreadyStatechange = function () { if (xhr.readyState == 4) { if (xhr.status >= 200 && xhr.status < 300) { callback(xhr.responseText) } } } } // 通過定時器來模擬請求 var requestJsPolyill = (id, callback) => { setTimeout(() => { callback(id) }, 1000) } var judge = data => { info.push(data) if (books.length === info.length) { console.log('請求到的資料:', info) } } books.forEach(v => requestJsPolyill(v.id, judge))
每請求到一個書本的資訊就追加到info
陣列中,每次追加後,來判斷books
與info
的長度是否相同,如果相同,則代表所有書本資訊均已請求完畢,如果不同則代表尚有書本資訊未請求成功,我們正是通過這種方式來處理並行請求,可以看到的是Promise
這種方式正是對原生JS的一種化用,或者說是一種更好的改變,所以也就符合了“瀉玉”這一階段
// 儲存獲取到的書本資訊 var info = [] var f = new Promise(resolve => { books.forEach(v => { // 根據books中每個id進行請求 request(v.id).then(() => { // 每請求到一個書本資訊都會放在info中 info.push(v.id) // 當請求完的資訊數量與原始書本的數量對應起來時,則代表全部請求完成 if (books.length === info.length) { resolve(info) } }) }) }) // 獲取完全部書本資訊後執行then方法 f.then(data => { console.log('請求到的資料:', data) })
由於map
方法會返回一個新陣列,所以此處通過map
來對books
中的每一個書本id都加工成一個請求,通過request
來完成這個請求,而request
又會返回一個Promise
物件,這樣一來,返回的這個新陣列中的每個成員就都是一個Promise
物件,而Promise.all
方法在接收到這個新陣列後,會並行執行所有Promise
物件,等到所有Promise
物件都決議後,then
方法才會被呼叫。使用async
來完成這個需求,無論是程式碼簡潔程度還是可讀性,都大大的超越了“翼然”和“瀉玉”這兩個階段,也可以說這正是“沁芳”的獨特所在
// 當新陣列中的所有Promise全部決議後,then會被如期呼叫 var f = Promise.all(books.map(async v => await request(v.id))) f.then(data => { console.log('請求到的資料:', data) })
我們分別使用了三種方式來處理並行請求,期間我們也闡述了它們各自的特點,而這也正好對應了文章開頭所提到的材料作文兩個部分:眾人題匾的三種方式以及對三種方式的評價。在Promise未面世之前,我們通常使用原生JavaScript
來處理請求,常用的手法也自然是使用回撥地獄,這一階段算是處於初始階段,也就正好對應了“翼然”這一層面,而通過對原生JavaScript請求方式的改善,將多層巢狀逐漸扁平化來優化程式碼,通過這一點Promise
也正符合了“瀉玉”這一階段,看到async
的實現方式才明白原來程式碼還可以如此優雅,比如可讀性、擴充套件性都要比前者強出不少,可能這大概就是創新的魅力所在了吧。無論是“翼然”還是“瀉玉”,距離我們理想的程式碼層面尚有些許不足,而正是這些不足的存在,我們才能一步一步的創新、前進,最終達到“沁芳”的理想層面
到此這篇關於Javascript如何理解全國甲卷高考作文的文章就介紹到這了,更多相關js理解全國甲卷高考作文內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45