加州野火空氣品質不佳 專家:恐增染疫機會

摘錄自2020年09月19日中央通訊社美國報導

美國疫情未退,加州又陷野火災情,空氣品質不佳,美國疾病管制暨預防中心(CDC)專家今天(19日)警告,煙塵可能刺激肺部,造成發炎,削弱免疫系統,使人更易感染新型冠狀病毒。

媒體報導,煙塵的覆蓋範圍大,加州不少醫院的急診或門診,氣喘患者增加。醫生擔心,2019冠狀病毒疾病(COVID-19,武漢肺炎)加上即將到來的流感季節,還有野火煙塵產生的呼吸疾病患者,會占用一定程度的醫療資源。

一名肺部專科醫生說,即使短時間暴露在煙霧中,也會降低人體對抗感染的能力。過去幾週隨著野火災情擴大,因呼吸問題就醫的患者大量增加。煙霧當中的微粒會使人體內的呼吸道黏膜變乾、發炎,使身體難以抵抗傳染來源。野火讓空氣變乾,體內呼吸道的黏液減少,呼吸道與黏膜會發炎、腫脹,對任何外來的病原更沒有抵抗力。

污染治理
國際新聞
加州
美國
野火
武漢肺炎
空氣污染

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!

美國再現罕見蚊類媒介致死傳染病 衛生當局呼籲:夜間勿出門

摘錄自2020年09月19日蘋果日報美國報導

新冠肺炎(武漢肺炎)疫情未見趨緩,美國部分地區又傳出現罕見的蚊媒傳染病,且已造成數人死亡。《CNN》報導,密西根州衛生與公共服務部(MDHHS)15日宣布,該州西南部又確認4起民眾感染「東部馬腦炎」(EEE,Eastern Equine Encephalitis)病例,其中2人已經死亡,目前密西根州已有7明確診案例,其中3人死亡。

東部馬腦炎是一種以蚊子作為媒介的人畜共通傳染病,雖然罕見,但卻可能致死。CDC去年接獲的通報病例與死亡人數就已出現了不尋常的增加,達到38例。

密西根州10個郡的22匹馬,也被驗出感染了EEE,是去年此時通報動物感染數量的兩倍,當局正在多個高風險地區礤取空中行動滅蚊,以降低傳播病毒媒介的蚊子數量。

 

生物多樣性
國際新聞
蚊子
CDC
人畜共通傳染病

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

英國石油轉型能源公司 11億美元投資離岸風電

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

氣候變遷影響更甚疫情 英王儲籲各界迅速行動

摘錄自2020年9月21日中央社報導

英國王儲查爾斯今天(21日)警告,氣候變遷危機影響更甚2019冠狀病毒疾病(COVID-19),敦促全球應將這波疫情視為採取行動的契機。

查爾斯(Prince Charles)說:「若未以史無前例的速度及規模,迅速且立即採取行動,我們將錯失為更永續、更包容的未來『重置』的短暫機會。」

查爾斯要向各界傳遞的訊息,包括上述言論,將在明天登場的紐約「氣候週」(Climate Week)線上開幕時播放。現年71歲的查爾斯3月時曾染疫,而他長期以來都是永續發展及對抗氣候變遷行動的擁護者。

氣候變遷
國際新聞
英國
武漢肺炎
疫情看氣候與能源

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

男人最愛的這項熱血汽車運動,真的很爽!

除了可以感受到賽車的熱烈氣氛以外,還可以近距離看到不同賽車的結構和技術亮點。當然了,還可以去了解一下賽車手究竟都是怎樣的人,究竟真的是“超人么”。這次的視頻,我們還特別找到了珠海高卡車隊的老闆兼車手王遠先生,去了解一下賽車究竟是怎麼一回事如。

對於喜歡汽車的朋友來說,總會看過一點關於賽車的東西。不過對於大部分對汽車不太熟悉的朋友,賽車貌似離我們非常遙遠,簡直好像是另外一個星球的事情。而賽車往往也是很高深莫測的精密机械,有超凡的性能,連駕駛賽車的車手也好像需要類似飛行員的體質和能力,才能駕馭這種可怕的機器!

真的是這樣么?

為了探尋這個秘密,我們到了珠海國際賽車場ZIC,去觀看泛珠三角賽車節春季賽(簡稱泛珠春季賽)。泛珠春季賽基本集合了大部分常見的賽車類別,包括方程式、prototype、GT、TCR、漂移賽車和改裝房車等等。除了可以感受到賽車的熱烈氣氛以外,還可以近距離看到不同賽車的結構和技術亮點。當然了,還可以去了解一下賽車手究竟都是怎樣的人,究竟真的是“超人么”。

這次的視頻,我們還特別找到了珠海高卡車隊的老闆兼車手王遠先生,去了解一下賽車究竟是怎麼一回事如。如果想體驗賽車,又有什麼門檻。當然了,我們也對他們車隊一台GK5賽車進行剖析,看看它究竟和我們一般街道行駛的飛度又有什麼相同和不同的地方。

如果你對賽車好奇,又想了解一下賽車究竟是怎麼回事,或者已經是一個熱血賽車迷的話,就不要錯過本期的視頻了。

本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

曾月銷40000輛的SUV,才賣了3年就停產了?

)。雖然大多時候汽車的停產都難免讓人傷感惋惜,但這一次顯然不太一樣,坊間大眾的聲音可是十分的多樣,而也對實際情況相當好奇。

清明節前,我們得知了一個比較沉重的消息,曾經月銷4萬的神車寶駿560,居然停產了!

為了給旗下重點產品讓路,滿足新產品的產能需求,寶駿汽車於近日停產了寶駿560車型(你明擺着就是說我560不重要嘍?)。雖然大多時候汽車的停產都難免讓人傷感惋惜,但這一次顯然不太一樣,坊間大眾的聲音可是十分的多樣,而也對實際情況相當好奇。

本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※教你寫出一流的銷售文案?

※超省錢租車方案

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※產品缺大量曝光嗎?你需要的是一流包裝設計!

【實拍】能賣得過凱美瑞邁騰?20萬級最熱門中型車到了!

而車尾造型簡潔,還帶有小鴨尾式的隆起。比較讓人費解的是它那雙C字型尾燈,雖然個性,但放在一款大尺寸的B級車身上顯得小氣,與簡潔明了的頭燈也沒太大呼應。內裝部分,它的設計沒有我們想象中那麼動感,造型四平八穩,反倒是具有幾分商務氣息。

近日,虎哥收到一則重磅消息,那就是在廣州地區的一家廣汽本田4S店已經有全新一代雅閣到店!聽到這一則消息的虎哥馬上放開手中的糯米雞,帶上小夥伴飛奔到這家廣汽本田4S店!

視頻看完還沒過癮?咱們繼續往下看。

其實雅閣對於國內朋友來說是一款相當熟悉的車型,而對於廣東地區的朋友來說,它更加是屬於具有特殊情懷的車型!早在1999年3月份,第6代雅閣就正式在廣州實現國產,作為廣汽本田成立后推出的第一款車型它被寄予厚望。

而截止到2002年第6代車型停產,它銷量一直很火爆,耐用、駕駛舒適成為它的最大標籤!在1999年-2002年間它銷量累計達到了13.8萬

輛!

緊接着推出的7代雅閣也一度造成一車難求的現象,也是經過兩代車型的努力,雅閣車型在家用中型車市場確立了標杆地位。

而8代雅閣以前衛、富有動感的外觀,實用的大空間亦獲得優秀的市場表現。

然而,從9代雅閣開始,“鍍鉻狂魔式”的前臉造型,和略顯臃腫的車身線條讓雅閣車型的油膩指數直線飆升!也是在這一代開始人們更多的認為它其實是一輛大叔座駕。

當然,廣汽本田也意識到這代車型設計有些用力過猛,所以在後來改款的9.5代設計向運動感回歸,銷量得以上升!

時至今日,第10代雅閣也即將來到我們身邊,“油膩”這個標籤也徹底與它脫離了關係!而關於它的具體細節我們就來細細分析。

10代雅閣的前臉營造出強烈的視覺衝擊力,看實車的時候這種感覺尤為明顯。中網上粗壯的一條鍍鉻飾條立體感強,而頭燈內部一字排開的LED燈組,十分不低調!

(注:本文圖片拍攝場地為廣汽本田第一店)

而設計師為側面造型畫下了濃墨重彩的一筆,Coupe式的車身設計,具有溜背式的車尾造型,車頂弧線平滑。而A柱的位置比上一代車型延後了100mm,發動機艙更修長、造型也被壓得更低,運動感已相當明顯。

輪轂的造型比較動感,但從目前的信息來看,雅閣的1.5T頂配車型也只配備17英寸的輪圈,它放在10代雅閣身上只是顯得剛剛夠用。想營造出讓人熱血噴張的運動感,它遠遠不行。或者廠家是出於對減低油耗的考慮,才限制了輪圈規格。畢竟它採用的是米其林primacy 3st浩悅系列 225/50 R17 規格的輪胎,它是一款注重降低油耗同時具備一定的操控性的輪胎型號。

尾部帶有真雙出排氣,這點是比較厚道的。而車尾造型簡潔,還帶有小鴨尾式的隆起。比較讓人費解的是它那雙C字型尾燈,雖然個性,但放在一款大尺寸的B級車身上顯得小氣,與簡潔明了的頭燈也沒太大呼應。

內裝部分,它的設計沒有我們想象中那麼動感,造型四平八穩,反倒是具有幾分商務氣息。

而新車型的內飾在細節處理方面有了較明顯進步。它加入了深色的木紋飾板和金屬拉絲材質進行點綴,比以前採用的鋼琴烤漆更顯檔次感。而且做工水準也更符合B級車定位。

儀錶盤左側設置了液晶显示屏,它能显示的多種信息,實用性不錯。值得一提的是,中控台上獨立式的8英寸多媒體觸控屏操作流暢,系統反應很快,而且显示界面也簡潔而細膩!比上一代車型好用不少,而兩側設置有實體按鍵,在開車過程中盲操作也便利,這提高了駕駛安全性。

而中控屏支撐Honda CONNECT功能,這是一套本田開發的智能互聯繫統。頂配車型帶有前排座椅通風、加熱功能,雙區自動空調還帶有空氣凈化功能,而詳細的配置信息會在後期公布。

這個內飾,並不能給人驚艷感,但它實用性很不錯,我想用一個“功能產生美”來形容它最貼切!

本田的乘坐空間最大化理念在新車型上依然有很好的體現,它溜背式的尾部設計沒有對後排頭部空間帶來過多影響。而對於身高177cm的虎哥來說,它營造出接近3拳的腿部空間,翹個二郎腿很合適。

而座椅柔軟程度和日產天籟有得一拼,坐墊長度也足夠,對於大腿的承托到位,中央扶手的長度和高度也到位,舒適性高!

只是稍有遺憾的是後排乘客能享受到的配置基本上只有後排出風口和中央扶手上帶有的兩個杯架。

關於新車預定:

銷售人員表示,第10代雅閣現在已經接受預定,喜歡它的朋友可以多加留意,因為車型還沒上市,所以提車時間現在還不能確定。

來到4S店看全新雅閣的人真的很多,可見它對於消費者吸引力還是比較大,而與這些潛在客戶交談時,他們也表示新車型內飾實用性強、做工有了進步!

寫在最後:第10代雅閣即將到來,它的造型無疑有了脫胎換骨般的變化,其造型確實富有運動感、衝擊力!而內飾的質感得到進步,但是整體水準仍然只屬於B級車應該有的水平,乘坐空間表現出色,座椅很舒適!1.5T+CVT的動力總成雖值得期待,但2.0T+10AT車型的缺失確實有些遺憾,不過作為主力銷售的1.5T車型到底具備多大的競爭力,那就要等待後期它的配置和價格信息公布!

特別鳴謝以下經銷商提供拍攝車輛:廣汽本田第一店;

電話:020-36312608;地址:廣東省廣州市白雲區黃石東路448號。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

12萬買1.6T合資緊湊型SUV?看完恍然大悟!

7-2。9米C級=中大型車長度4。8米-5米,軸距2。8-3米,排量超過2。4LD級=大型車長度超過5米,軸距超過3米,排量超過3L呃,根據這個分類方法,不同的車型基本都可以找到各自對應的分類,而且通過看車型的分類級別,就能一目瞭然找到自己要的大小的車子。

昨晚,現代ENCINO上市

除了分體式大燈以及標配的1.6T發動機十分好看之外

還注意到一個有意思的地方

有媒體竟然叫它緊湊型SUV!

緊湊型SUV?

就是和CR-V、RAV4榮放一個級別?

只要12萬而且還標配1.6T?

這也太划算了吧

然而,事情沒那麼簡單,這貨的尺寸為4195*1800*1575mm,軸距為2600mm

長度和軸距甚至還不如本田XR-V這種小型SUV

比起中國車企的東南DX3、傳祺GS3等小型SUV也差了不少

這樣的尺寸也敢叫緊湊型SUV,是梁靜茹給它的勇氣嗎?

吐槽的同時

也必須弄清一個概念

汽車級別怎麼劃分的?

如今多數媒體車企給車型劃分分類的標準多是歐洲標準

也就是大眾汽車的分級辦法,綜合排量、車型大小等因素分為

A00級、A0級、A級、B級、C級、D級。

A00級=微型車

長度4米內,軸距2-2.3米

A0級=小型車

長度4-4.3米,軸距2.3-2.5米

A級=緊湊型車

長度4.2-4.6米,軸距2.5-2.7米

B級=中型車

長度4.5-4.9米,軸距2.7-2.9米

C級=中大型車

長度4.8米-5米,軸距2.8-3米,排量超過2.4L

D級=大型車

長度超過5米,軸距超過3米,排量超過3L

呃,根據這個分類方法,不同的車型基本都可以找到各自對應的分類,而且通過看車型的分類級別,就能一目瞭然找到自己要的大小的車子。因此這一套分類方法十分流行。

然而,這套方法的分級卻經常被車企混用,比如這一次,尺寸4195*1800*1575mm,軸距為2600mm的ENCINO也敢叫自己緊湊型SUV。

除了ENCINO之外,還有不少這類型的例子:

咱們熟悉的緊湊型轎車科魯茲,在官網pDF上把自己叫做“新銳性能中級車”,這,莫非科魯茲是中型轎車?

非也,中型車與中級車一字之差,但是差距可不是一星半點,前文中說到中型車是歐洲分類標準,而中級車則是咱們中國的標準了,依照中國汽車分類標準(GB9417-89)的分級方法,中級車屬於排量1.6-2.5L的車型,因此依照這個標準來看,科魯茲還確實是中級車,而且大多數緊湊型車也確實可以叫自己中級車,不過在咱們大多數人的理解中,中級車=中型車啊!因此科魯茲也確實有鑽這個空子的嫌疑。

為了產品賣得好一點,吹出一點牛皮也是合情合理的,不過相比上面兩款車型的手法,下面這些才是真大佬!

奔馳S級:再次發明汽車

奔馳S級在上市之初打出了許多十分誇張的口號,比如:“汽車發明者,再次發明汽車”“再見愛迪生”等等,雖然S級從設計的角度來說確實達到了一個新高度,但是再次發明汽車的口號也有些太狂了。

昂科威:百萬級最好的隔音

昂科威是別克旗下的中型SUV,售價21.99-31.99萬,這個價位的SUV老老實實賣車才是王道,然而昂科威並不安分,在上市之初昂科威便把百萬內最好的隔音作為賣點,要知道不同價位車型之間的差別可是十分大的,昂科威這口號也是夠大膽的,不過經實測,昂科威隔音確實比百萬級的卡宴更好。

君越:圖書館級靜音

同樣宣傳隔音的還有君越,這一次君越使用了圖書館級靜音水準這個詞彙,而根據《圖書館、博物館、美術館、展覽館衛生標準》(GB9669-1996)規定,圖書館的噪聲標準為≤50dB(A),這樣的噪音數值恐怕君越只有怠速工況下能夠達到吧~

攬勝:越野車中的勞斯萊斯

嚴格來說,這個稱號是廣大粉絲送的,不過也是非常霸氣的一個稱號了,除了越野車中的勞斯萊斯之外,路虎還有英國皇室狩獵專用車等頭銜,不過勞斯萊斯的越野車馬上就要上市了…

總結:

汽車廣告與宣傳中往往用到許多誇張的詞彙,越級、澎湃、奢華等詞語的出鏡率十分高,這樣的宣傳往往能讓人印象深刻,不過如果真的太相信這些宣傳詞彙,到頭來往往會讓人失望,汽車說到底也只是普通商品,既然是商品那麼一分錢一分貨這個道理還是適用的,用10萬元買到20萬的品質這種事情往往不會存在的,作為消費者,在看車企宣傳的同時一定要自己辨別,這樣才能避免被騙哦~本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

Express4.x之中間件與路由詳解及源碼分析,Express4.x之API:express,Express4.x之API:express

  • Application.use()
  • Application.router()
  • express核心源碼模擬

 一、express.use()

1.1app.use([path,] callback [, callback …])

通過語法結構可以看到Application.use()參數分別有以下幾種情形:

app.use(function(){...}); //給全局添加一个中間件
app.use(path,function(){...}); //給指定路由path添加一个中間件
app.use(function(){...}, function(){...}, ...); //給全局添加n个中間件
app.use(path,function(){...},function(){...}, ...); //給指定路由path添加n个中間件

關於path最簡單也是最常用的就是字符串類型(例:‘/abcd’);除了字符串Express還提供了模板和正則格式(例:’/abc?d‘, ‘/ab+cd‘, ‘/ab\*cd‘, ‘/a(bc)?d‘, ‘/\/abc|\/xyz/‘);除了單個的字符串和模板還可以將多個path作為一個數組的元素,然後將這個數組作為use的path,這樣就可以同時給多個路由添加中間件,詳細內容可以參考官方文檔:https://www.expressjs.com.cn/4x/api.html#path-examples。

關於callbakc多個或單个中間件程序這已經再語法結構中直觀的體現出來了,這裏重點來看看回調函數的參數:

app.use(function(req,res,next){...}); //必須提供的參數 
app.use(function(err,req,res,next){...}); //錯誤中間件需要在最前面添加一個錯誤參數

關於中間件的簡單應用:

let express = require('./express');
let app = express();
app.use('/',function(req,res,next){
    console.log("我是一個全局中間件");
    next(); //每个中間件的最末尾必須調用next
});

app.use('/',function(err,req,res,next){
    console.log("我是一個全局錯誤中間,當發生錯誤是調用")    
    console.error(err.stack);
    res.status(500).send('服務出錯誤了!');
    //由於這個錯誤處理直接響應了客戶端,可以不再調用next,當然後面還需要處理一些業務的話也是可以調用next的
});

1.2簡單的模擬Express源碼實現Appliction.use()以及各個請求方法的響應註冊方法(這裏個源碼模擬路由概念還比較模糊,所以使用請求方法的響應註冊API,而沒有使用路由描述):

 1 //文件結構
 2 express
 3     index.js
 4 //源碼模擬實現
 5 let http = require("http");
 6 let url = require('url');
 7 function createApplication(){
 8     //app是一個監聽函數
 9     let app = (req,res) =>{
10         //取出每一個層
11         //1.獲取請求的方法
12         let m = req.method.toLowerCase();
13         let {pathname} = url.parse(req.url,true);
14 
15         //通過next方法進行迭代
16         let index = 0;
17         function next(err){
18             //如果routes迭代完成還沒有找到,說明路徑不存在
19             if(index === app.routes.length) return res.end(`Cannot ${m} ${pathname}`);
20             let {method, path, handler} = app.routes[index++];//每次調用next就應該取下一個layer
21             if(err){
22                 if(handler.length === 4){
23                     handler(err,req,res,next);
24                 }else{
25                     next(err);
26                 }
27             }else{
28                 if(method === 'middle'){ //處理中間件
29                     if(path === '/' || path === pathname || pathname.startsWith(path+'/')){
30                         handler(req,res,next);
31                     }else{
32                         next();//如果這个中間件沒有匹配到,繼續通過next迭代路由容器routes
33                     }
34                 }else{ //處理路由
35                     if( (method === m || method ==='all') && (path === pathname || path === '*')){ //匹配請求方法和請求路徑(接口)
36                         handler(req,res);//匹配成功后執行的Callback
37                     }else{
38                         next();
39                     }
40                 }
41             }
42         }
43         next();
44     }
45     app.routes = [];//路由容器
46     app.use = function(path,handler){
47         if(typeof handler !== 'function'){
48             handler = path;
49             path = '/';
50         }
51         let layer = {
52             method:'middle', //method是middle就表示它是一个中間件
53             path,
54             handler
55         }
56         app.routes.push(layer);
57     }
58     app.all = function(path,handler){
59         let layer = {
60             method:'all',
61             path,
62             handler
63         }
64         app.routes.push(layer);
65     }
66     console.log(http.METHODS);
67     http.METHODS.forEach(method =>{
68         method = method.toLocaleLowerCase();
69         app[method] = function (path,handler){//批量生成各個請求方法的路由註冊方法
70             let layer = {
71                 method,
72                 path,
73                 handler
74             }
75             app.routes.push(layer);
76         }
77     });
78     //內置中間件,給req擴展path、qury屬性
79     app.use(function(req,res,next){
80         let {pathname,query} = url.parse(req.url,true);
81         let hostname = req.headers['host'].split(':')[0];
82         req.path = pathname;
83         req.query = query;
84         req.hostname = hostname;
85         next();
86     });
87     //通過app.listen調用http.createServer()掛在app(),啟動express服務
88     app.listen = function(){
89         let server = http.createServer(app);
90         server.listen(...arguments);
91     }
92     return app;
93 }
94 module.exports = createApplication;

View Code

測試模擬實現的Express:

 1 let express = require('./express');
 2 
 3 let app = express();
 4 
 5 app.use('/',function(req,res,next){
 6     console.log("我是一個全局中間件");
 7     next();
 8 });
 9 app.use('/user',function(req,res,next){
10     console.log("我是user接口的中間件");
11     next();
12 });
13 app.get('/name',function(req,res){
14     console.log(req.path,req.query,req.hostname);
15     res.end('zfpx');
16 });
17 app.post('/name',function(req,res){
18     res.end('post name');
19 });
20 
21 
22 app.all("*",function(req,res){
23     res.end('all');
24 });
25 
26 app.use(function(err,req,res,next){
27     console.log(err);
28     next();
29 });
30 
31 app.listen(12306);

View Code

在windows系統下測試請求:

 

 

關於源碼的構建詳細內容可以參考這個視頻教程:app.use()模擬構建視頻教程,前面就已經說明過這個模式實現僅僅是從表面的業務邏輯,雖然有一點底層的雛形,但與源碼還是相差甚遠,這一部分也僅僅只是想幫助理解Express採用最簡單的方式表現出來。

1.3如果你看過上面的源碼或自己也實現過,就會發現Express關於中間件的添加方式除了app.use()還有app.all()及app.METHOD()。在模擬源碼中我並未就use和all的差異做處理,都是採用了請求路徑絕對等於path,這種方式是all的特性,use的path實際表示為請求路徑的開頭:

app.use(path,callback):path表示請求路徑的開頭部分。

app.all(path,callback):paht表示完全等於請求路徑。

app.METHOD(path,callback):並不是真的有METHOD這個方法,而是指HTTP請求方法,實際上表示的是app.get()、app.post()、app.put()等方法,而有時候我們會將這些方法說成用來註冊路由,這是因為路由註冊的確使用這些方法,但同時這些方法也是可以用作中間的添加,這在前一篇博客中的功能解析中就有說明(Express4.x之API:express),詳細見過後面的路由解析就會更加明了。

 二、express.router()

2.1在實例化一個Application時會實例化一個express.router()實例並被添加到app._router屬性上,實際上這個app使用的use、all、METHOD時都是在底層調用了該Router實例上對應的方法,比如看下面這些示例:

 1 let express = require("express");
 2 let app = express();
 3 
 4 app._router.use(function(req,res,next){
 5     console.log("--app.router--");
 6     next();
 7 });
 8 
 9 app._router.post("/csJSON",function(req,res,next){
10     res.writeHead(200);
11     res.write(JSON.stringify(req.body));
12     res.end();
13 });
14 
15 app.listen(12306);

上面示例中的app._router.use、app._router.post分別同等與app.use、app.post,這裏到這裏也就說明了上一篇博客中的路由與Application的關係Express4.x之API:express。

2.2Express中的Router除了為Express.Application提供路由功能以外,Express也將它作為一個獨立的路由工具分離了出來,也就是說Router自身可以獨立作為一個應用,如果我們在實際應用中有相關業務有類似Express.Application的路由需求,可以直接實例化一個Router使用,應用的方式如下:

let express = require('/express');
let router = express.Router();
//這部分可以詳細參考官方文檔有詳細的介紹

2.3由於這篇博客主要是分析Express的中間件及路由的底層邏輯,所以就不在這裏詳細介紹某個模塊的應用,如果有時間我再寫一篇關於Router模塊的應用,這裏我直接上一份模擬Express路由的代碼以供參考:

文件結構:

express //根路徑
    index.js //express主入口文件
    application.js //express應用構造模塊
    router //路由路徑
        index.js //路由主入口文件
        layer.js //構造層的模塊
        route.js //子路由模塊

Express路由系統的邏輯結構圖:

模擬代碼(express核心源碼模擬):

1 //express主入口文件
2 let Application = require('./application.js');
3 
4 function createApplication(){
5     return new Application();
6 }
7 
8 module.exports = createApplication;

index.js //express主入口文件

 1 //用來創建應用app
 2 let http = require('http');
 3 let url = require('url');
 4 
 5 //導入路由系統模塊
 6 let Router = require('./router');
 7 
 8 const methods = http.METHODS;
 9 
10 //Application ---- express的應用系統
11 function Application(){
12     //創建一個內置的路由系統
13     this._router = new Router();
14 }
15 
16 //app.get ---- 實現路由註冊業務
17 // Application.prototype.get = function(path,...handlers){
18 //     this._router.get(path,'use',handlers);
19 // }
20 
21 methods.forEach(method => {
22     method = method.toLocaleLowerCase();
23     Application.prototype[method] = function(path,...handlers){
24         this._router[method](path,handlers);
25     }
26 });
27 
28 //app.use ---- 實現中間件註冊業務
29 //這裏模擬處理三種參數模式:
30 // -- 1個回調函數:callback
31 // -- 多個回調函數:[callback,] callback [,callback...]
32 // -- 指定路由的中間件:[path,] callback [,callback...]
33 // -- 注意源碼中可以處理這三種參數形式還可以處理上面數據的數組形式,以及其他Application(直接將其他app上的中間件添加到當前應用上)
34 Application.prototype.use = function(fn){
35     let path = '/';
36     let fns = [];
37     let arg = [].slice.call(arguments);
38     if(typeof fn !== 'function' && arg.length >= 2){
39         if(typeof arg[0] !== 'string'){
40             fns = arg;
41         }else{
42             path = arg[0];
43             fns = arg.slice(1);
44         }
45     }else{
46         fns = arg;
47     }
48     this._router.use(path,'use',fns);
49 }
50 
51 Application.prototype.all = function(fn){
52     let path = '/';
53     let fns = [];
54     let arg = [].slice.call(arguments);
55     if(typeof fn !== 'function' && arg.length >= 2){
56         if(typeof arg[0] !== 'string'){
57             fns = arg;
58         }else{
59             path = arg[0];
60             fns = arg.slice(1);
61         }
62       }else{
63         fns = arg;
64     }
65     this._router.use(path,'all',fns);
66 }
67 
68 //將http的listen方法封裝到Application的原型上
69 Application.prototype.listen = function(){
70     let server = http.createServer((req,res)=>{
71         //done 用於當路由無任何可匹配項時調用的處理函數
72         function done(){
73             res.end(`Cannot ${req.url} ${req.method}`);
74         }
75         this._router.handle(req,res,done); //調用路由系統的handle方法處理請求
76     });
77     server.listen(...arguments);
78 };
79 
80 module.exports = Application;

application.js //express應用構造模塊

 1 //express路由系統
 2 const Layer = require('./layer.js');
 3 const Route = require('./route.js');
 4 
 5 const http = require('http');
 6 const methods = http.METHODS;
 7 
 8 const url = require('url');
 9 
10 
11 //路由對象構造函數
12 function Router(){
13     this.stack = [];
14 }
15 
16 //router.route ---- 用於創建子路由對象route與主路由上層(layer)的關係
17 //並將主路由上的層緩存到路由對象的stack容器中,該層建立路徑與子路由處理請求的關係
18 Router.prototype.route = function(path){
19     let route = new Route();
20     let layer = new Layer(path,route.dispatch.bind(route));
21     this.stack.push(layer);
22     return route;
23 }
24 
25 //router.get ---- 實現路由註冊
26 //實際上這個方法調用router.route方法分別創建一個主路由系統層、一個子路由系統,並建立兩者之間的關係,詳細見Router.prototype.route
27 //然後獲取子路由系統對象,並將回調函數和請求方法註冊在這個子路由系統上
28 
29 
30 // Router.prototype.get = function(path,handlers){
31 //     let route = this.route(path);
32 //     route.get(handlers);
33 // }
34 
35 methods.forEach(method =>{ 
36     method = method.toLocaleLowerCase();
37     //注意下面這個方法會出現內存泄漏問題,有待改進
38     Router.prototype[method] = function(path, handlers){
39         let route = this.route(path);
40         route[method](handlers);
41     }
42 });
43 
44 //router.use ---- 實現中間件註冊(按照路由開頭的路徑匹配,即相對路由匹配)
45 Router.prototype.use = function(path,routerType,fns){
46     let router = this;
47     fns.forEach(function(fn){
48         let layer = new Layer(path,fn);
49         layer.middle = true; //標記這個層為相對路由中間件
50         layer.routerType = routerType;
51         router.stack.push(layer);
52     });
53 }
54 
55 //調用路由處理請求
56 Router.prototype.handle = function(req,res,out){
57     let {pathname} = url.parse(req.url);
58     let index = 0;
59     let next = () => {
60         if(index >= this.stack.length) return out();
61         let layer = this.stack[index++];
62         if(layer.middle && (layer.path === '/' || pathname === layer.path || pathname.startsWith(layer.path + '/'))){
63             //處理中間件
64             if(layer.routerType === 'use'){
65                 layer.handle_request(req,res,next);
66             }else if(layer.routerType === 'all' && layer.path === pathname){
67                 layer.handle_request(req,res,next);
68             }else{
69                 next();
70             }
71         }else if(layer.match(pathname)){
72             //處理響應--更準確的說是處理具體請求方法上的中間件或響應
73             layer.handle_request(req,res,next);
74         }else{
75             next();
76         }
77     }
78     next();
79 }
80 
81 module.exports = Router;

index.js //路由主入口文件

 1 //Layer的構造函數
 2 function Layer(path,handler){
 3     this.path = path; //當前層的路徑
 4     this.handler = handler;  //當前層的回調函數
 5 }
 6 
 7 //判斷請求方法與當前層的方法是否一致
 8 Layer.prototype.match = function(pathname){
 9     return this.path === pathname;
10 }
11 
12 //調用當前層的回調函數handler
13 Layer.prototype.handle_request = function(req,res,next){
14     this.handler(req,res,next);
15 }
16 
17 module.exports = Layer;

layer.js //構造層的模塊

 1 //Layer的構造函數
 2 function Layer(path,handler){
 3     this.path = path; //當前層的路徑
 4     this.handler = handler;  //當前層的回調函數
 5 }
 6 
 7 //判斷請求方法與當前層的方法是否一致
 8 Layer.prototype.match = function(pathname){
 9     return this.path === pathname;
10 }
11 
12 //調用當前層的回調函數handler
13 Layer.prototype.handle_request = function(req,res,next){
14     this.handler(req,res,next);
15 }
16 
17 module.exports = Layer;

route.js //子路由模塊

測試代碼:

 1 let express = require('./express');
 2 let app = express();
 3 
 4 
 5 app.use('/name',function(req,res,next){
 6     console.log('use1');
 7     next();
 8 });
 9 app.use(function(req,res,next){
10     console.log('use2-1');
11     next();
12 },function(req,res,next){
13     console.log('use2-2');
14     next();
15 });
16 
17 app.all('/name',function(req,res,next){
18     console.log('all-1');
19     next();
20 });
21 app.all('/name/app',function(req,res,next){
22     console.log('all-2');
23     next();
24 });
25 
26 app.get('/name/app',function(req,res){
27     res.end(req.url);
28 });
29 // console.log(app._router.stack);
30 app.listen(12306);

View Code

測試結果:

 

 

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

Dart Memo for Android Developers

Dart Memo for Android Developers

Dart語言一些語法特點和編程規範.

本文適合: 日常使用Kotlin, 突然想寫個Flutter程序的Android程序員.

Dart語言

完整的請看A tour of the Dart language

  • 創建對象可以不用new. -> 並且規範不讓用new, lint會報錯.
  • 聲明變量可以用var, 也可以用具體類型如String. 不變量用final, 常量用const.
  • 沒有訪問修飾符, 用_來表示私有: 文件級別.
  • 字符串可以用單引號'.
  • 語句結尾要用;.
  • 創建數組可以用: var list = [1, 2, 3];.
  • assert()常用來斷定開發時不可能會出現的情況.
  • 空測試操作符: ??.
  • 過濾操作符: where.
  • 兩個點..表示鏈式調用.
  • dynamic說明類型未指定.
  • 除了throw異常, 還可以throw別的東西, 比如字符串.

函數

  • 函數返回值在函數最開頭, 可以不標. -> 但是規範會建議標註返回值.
bool isNoble(int atomicNumber) {
  return _nobleGases[atomicNumber] != null;
}
  • =>箭頭符號, 用來簡化一句話的方法.
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;

構造函數

  • 構造函數{}表示帶名字, 參數可選, 若要必選加上@required.
const Scrollbar({Key key, @required Widget child})
  • 構造函數名可以是ClassName或者ClassName.identifier.
  • 空構造函數體可以省略, 用;結尾就行:
class Point {
  double x, y;
  Point(this.x, this.y);
}

這裡會初始化相應的變量, 也不用聲明具體的參數類型.

  • factory構造, 可以用來返回緩存實例, 或者返回類型的子類:
factory Logger(String name) {
    return _cache.putIfAbsent(name, () => Logger._internal(name));
}

異步代碼

Future<String> lookUpVersion() async => '1.0.0';

Future checkVersion() async {
  var version = await lookUpVersion();
  // Do something with version
}

編程規範類

完整的規範在這裏: Effective Dart.

有一些Good和Bad的舉例, 這裏僅列出比較常用的幾項.

  • 文件名要蛇形命名: lowercase_with_underscores. 類名: UpperCamelCase.
  • 對自己程序的文件, 兩種import都可以(package開頭或者相對路徑), 但是要保持一致.
  • Flutter程序嵌套比較多, 要用結尾的,來幫助格式化.

本文緣由

年初的時候學了一陣子Flutter, 寫了各種大小demo. 結果隔了兩個月之後, 突然心血來潮想寫個小東西, 打開Android Studio, 首先發現創建Flutter程序的按鈕都不見了. (估計是Android Studio4.0升級之後Flutter的插件沒跟上).

接着用命令行創建了工程, 打開之後稍微整理了一下心情, 然後就….懵逼了.

突然不知道如何下手.
宏觀的東西還記得, 要用什麼package, 基本常用的幾個Widget都是啥, 但是微觀的, 忘了函數和數組都是咋定義的了.
這種懵逼的狀態令我很憤怒, 果然是上年紀了嗎, 無縫切換個語言都不行.

於是就想着還是寫個備忘錄吧.

References

  • A tour of the Dart language
  • Effective Dart

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案