Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
dr怎么繪制簡(jiǎn)筆畫(huà)效果的葉子?cdr中想要繪制一個(gè)簡(jiǎn)單的樹(shù)葉效果,該怎么繪制呢?下面我們就來(lái)看看cdr樹(shù)葉的繪制方法,需要的朋友可以參考下:
1、首先繪制一個(gè)圓,Ctrl+q轉(zhuǎn)曲。
2、用形狀工具雙擊刪除左右連個(gè)節(jié)點(diǎn)。
3、將上下兩個(gè)節(jié)點(diǎn)改為“尖突”。
4、調(diào)整為如圖形狀,不必太工整對(duì)稱,因?yàn)橐惺掷L的自然和隨意感。
5、將其復(fù)制一份,變形(向中間壓縮),放在中間,做成葉子紋理線條。
6、按f12將“角”的類型改為第二個(gè)。
7、用手繪工具繪制一條曲線,將葉片放在頂端,調(diào)整合適的方向。
8、如是復(fù)制多個(gè),排列在兩邊。完成。
9、拓展一下,類似的方法,我們可以做出各種各樣的葉片和造型。大家盡可能的發(fā)揮想象。
以上就是cdr樹(shù)葉的繪制方法,希望大家喜歡,軟件下載:http://www.coreldrawchina.com/xiazai.html。
鳥(niǎo)網(wǎng)作者:落v葉
出自蜂鳥(niǎo)網(wǎng)-人像攝影,原貼鏈接:https://m.fengniao.com/thread/11004426.html
攝影/落葉
模特/熙
地點(diǎn)/桂林
歡迎關(guān)注 蜂鳥(niǎo)網(wǎng)微信公眾號(hào):fengniaoweixin
vent Loop 是一個(gè)很重要的概念,指的是計(jì)算機(jī)系統(tǒng)的一種運(yùn)行機(jī)制。
JavaScript語(yǔ)言就采用這種機(jī)制,來(lái)解決單線程運(yùn)行帶來(lái)的一些問(wèn)題。
想要理解Event Loop,就要從程序的運(yùn)行模式講起。運(yùn)行以后的程序叫做“進(jìn)程”(process),一般情況下,一個(gè)進(jìn)程一次只能執(zhí)行一個(gè)任務(wù)。
如果有很多任務(wù)需要執(zhí)行,不外乎三種解決方法。
(1)排隊(duì)。因?yàn)橐粋€(gè)進(jìn)程一次只能執(zhí)行一個(gè)任務(wù),只好等前面的任務(wù)執(zhí)行完了,再執(zhí)行后面的任務(wù)。
(2)新建進(jìn)程。使用fork命令,為每個(gè)任務(wù)新建一個(gè)進(jìn)程。
(3)新建線程。因?yàn)檫M(jìn)程太耗費(fèi)資源,所以如今的程序往往允許一個(gè)進(jìn)程包含多個(gè)線程,由線程去完成任務(wù)。(進(jìn)程和線程的詳細(xì)解釋,請(qǐng)看這里。)
以JavaScript語(yǔ)言為例,它是一種單線程語(yǔ)言,所有任務(wù)都在一個(gè)線程上完成,即采用上面的第一種方法。一旦遇到大量任務(wù)或者遇到一個(gè)耗時(shí)的任務(wù),網(wǎng)頁(yè)就會(huì)出現(xiàn)”假死”,因?yàn)镴avaScript停不下來(lái),也就無(wú)法響應(yīng)用戶的行為。
你也許會(huì)問(wèn),JavaScript為什么是單線程,難道不能實(shí)現(xiàn)為多線程嗎?
這跟歷史有關(guān)系。JavaScript從誕生起就是單線程。原因大概是不想讓瀏覽器變得太復(fù)雜,因?yàn)槎嗑€程需要共享資源、且有可能修改彼此的運(yùn)行結(jié)果,對(duì)于一種網(wǎng)頁(yè)腳本語(yǔ)言來(lái)說(shuō),這就太復(fù)雜了。后來(lái)就約定俗成,JavaScript為一種單線程語(yǔ)言。(Worker API可以實(shí)現(xiàn)多線程,但是JavaScript本身始終是單線程的。)
如果某個(gè)任務(wù)很耗時(shí),比如涉及很多I/O(輸入/輸出)操作,那么線程的運(yùn)行大概是下面的樣子。
上圖的綠色部分是程序的運(yùn)行時(shí)間,紅色部分是等待時(shí)間??梢钥吹?,由于I/O操作很慢,所以這個(gè)線程的大部分運(yùn)行時(shí)間都在空等I/O操作的返回結(jié)果。這種運(yùn)行方式稱為”同步模式”(synchronous I/O)或”堵塞模式”(blocking I/O)。
如果采用多線程,同時(shí)運(yùn)行多個(gè)任務(wù),那很可能就是下面這樣。
上圖表明,多線程不僅占用多倍的系統(tǒng)資源,也閑置多倍的資源,這顯然不合理。
Event Loop就是為了解決這個(gè)問(wèn)題而提出的。Wikipedia這樣定義:
“Event Loop是一個(gè)程序結(jié)構(gòu),用于等待和發(fā)送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)”
簡(jiǎn)單說(shuō),就是在程序中設(shè)置兩個(gè)線程:一個(gè)負(fù)責(zé)程序本身的運(yùn)行,稱為”主線程”;另一個(gè)負(fù)責(zé)主線程與其他進(jìn)程(主要是各種I/O操作)的通信,被稱為”Event Loop線程”(可以譯為”消息線程”)。
上圖主線程的綠色部分,還是表示運(yùn)行時(shí)間,而橙色部分表示空閑時(shí)間。每當(dāng)遇到I/O的時(shí)候,主線程就讓Event Loop線程去通知相應(yīng)的I/O程序,然后接著往后運(yùn)行,所以不存在紅色的等待時(shí)間。等到I/O程序完成操作,Event Loop線程再把結(jié)果返回主線程。主線程就調(diào)用事先設(shè)定的回調(diào)函數(shù),完成整個(gè)任務(wù)。
可以看到,由于多出了橙色的空閑時(shí)間,所以主線程得以運(yùn)行更多的任務(wù),這就提高了效率。這種運(yùn)行方式稱為”異步模式“(asynchronous I/O)或”非堵塞模式”(non-blocking mode)。
這正是JavaScript語(yǔ)言的運(yùn)行方式。單線程模型雖然對(duì)JavaScript構(gòu)成了很大的限制,但也因此使它具備了其他語(yǔ)言不具備的優(yōu)勢(shì)。如果部署得好,JavaScript程序是不會(huì)出現(xiàn)堵塞的,這就是為什么node.js平臺(tái)可以用很少的資源,應(yīng)付大流量訪問(wèn)的原因。
以上是關(guān)于Event loop的概念,然而實(shí)際上的操作中我們會(huì)遇到非常多的問(wèn)題,讓我們無(wú)從下手,在這里我給大家介紹一個(gè)自己的qun,里面有很多熱情的大神,更有實(shí)際操作過(guò)的老手和老師,我也會(huì)不時(shí)分享學(xué)習(xí)的資料和視頻(2131 26486),填寫(xiě)并私聊我(落葉)直接領(lǐng)取。
在實(shí)際工作中,了解Event loop的意義能幫助你分析一些異步次序的問(wèn)題(當(dāng)然,隨著es7 async和await的流行,這樣的機(jī)會(huì)越來(lái)越少了)。除此以外,它還對(duì)你了解瀏覽器和Node的內(nèi)部機(jī)制有積極的作用;對(duì)于參加面試,被問(wèn)到一堆異步操作的執(zhí)行順序時(shí),也不至于兩眼抓瞎。
3. 瀏覽器上的實(shí)現(xiàn)
在JavaScript中,任務(wù)被分為T(mén)ask(又稱為MacroTask,宏任務(wù))和MicroTask(微任務(wù))兩種。它們分別包含以下內(nèi)容:
MacroTask: script(整體代碼), setTimeout, setInterval, setImmediate(node獨(dú)有), I/O, UI renderingMicroTask: process.nextTick(node獨(dú)有), Promises, Object.observe(廢棄), MutationObserver
需要注意的一點(diǎn)是:在同一個(gè)上下文中,總的執(zhí)行順序?yàn)橥酱a—>microTask—>macroTask[6]。這一塊我們?cè)谙挛闹袝?huì)講。
瀏覽器中,一個(gè)事件循環(huán)里有很多個(gè)來(lái)自不同任務(wù)源的任務(wù)隊(duì)列(task queues),每一個(gè)任務(wù)隊(duì)列里的任務(wù)是嚴(yán)格按照先進(jìn)先出的順序執(zhí)行的。但是,因?yàn)?strong>瀏覽器自己調(diào)度的關(guān)系,不同任務(wù)隊(duì)列的任務(wù)的執(zhí)行順序是不確定的。
具體來(lái)說(shuō),瀏覽器會(huì)不斷從task隊(duì)列中按順序取task執(zhí)行,每執(zhí)行完一個(gè)task都會(huì)檢查microtask隊(duì)列是否為空(執(zhí)行完一個(gè)task的具體標(biāo)志是函數(shù)執(zhí)行棧為空),如果不為空則會(huì)一次性執(zhí)行完所有microtask。然后再進(jìn)入下一個(gè)循環(huán)去task隊(duì)列中取下一個(gè)task執(zhí)行,以此類推。
注意:圖中橙色的MacroTask任務(wù)隊(duì)列也應(yīng)該是在不斷被切換著的。
本段大批量引用了《什么是瀏覽器的事件循環(huán)(Event Loop)》的相關(guān)內(nèi)容,想看更加詳細(xì)的描述可以自行取用。
4. Node上的實(shí)現(xiàn)
nodejs的event loop分為6個(gè)階段,它們會(huì)按照順序反復(fù)運(yùn)行,分別如下:
timers:執(zhí)行setTimeout() 和 setInterval()中到期的callback。
I/O callbacks:上一輪循環(huán)中有少數(shù)的I/Ocallback會(huì)被延遲到這一輪的這一階段執(zhí)行
idle, prepare:隊(duì)列的移動(dòng),僅內(nèi)部使用
poll:最為重要的階段,執(zhí)行I/O callback,在適當(dāng)?shù)臈l件下會(huì)阻塞在這個(gè)階段
check:執(zhí)行setImmediate的callback
close callbacks:執(zhí)行close事件的callback,例如socket.on("close",func)
不同于瀏覽器的是,在每個(gè)階段完成后,而不是MacroTask任務(wù)完成后,microTask隊(duì)列就會(huì)被執(zhí)行。這就導(dǎo)致了同樣的代碼在不同的上下文環(huán)境下會(huì)出現(xiàn)不同的結(jié)果。我們?cè)谙挛闹袝?huì)探討。
另外需要注意的是,如果在timers階段執(zhí)行時(shí)創(chuàng)建了setImmediate則會(huì)在此輪循環(huán)的check階段執(zhí)行,如果在timers階段創(chuàng)建了setTimeout,由于timers已取出完畢,則會(huì)進(jìn)入下輪循環(huán),check階段創(chuàng)建timers任務(wù)同理。
5. 示例
5.1 瀏覽器與Node執(zhí)行順序的區(qū)別
setTimeout(()=>{ console.log('timer1') Promise.resolve().then(function() { console.log('promise1') }) }, 0) setTimeout(()=>{ console.log('timer2') Promise.resolve().then(function() { console.log('promise2') }) }, 0) 瀏覽器輸出: time1 promise1 time2 promise2 Node輸出: time1 time2 promise1 promise2
在這個(gè)例子中,Node的邏輯如下:
最初timer1和timer2就在timers階段中。開(kāi)始時(shí)首先進(jìn)入timers階段,執(zhí)行timer1的回調(diào)函數(shù),打印timer1,并將promise1.then回調(diào)放入microtask隊(duì)列,同樣的步驟執(zhí)行timer2,打印timer2;
至此,timer階段執(zhí)行結(jié)束,event loop進(jìn)入下一個(gè)階段之前,執(zhí)行microtask隊(duì)列的所有任務(wù),依次打印promise1、promise2。
而瀏覽器則因?yàn)閮蓚€(gè)setTimeout作為兩個(gè)MacroTask, 所以先輸出timer1, promise1,再輸出timer2,promise2。
更加詳細(xì)的信息可以查閱《深入理解js事件循環(huán)機(jī)制(Node.js篇)》
為了證明我們的理論,把代碼改成下面的樣子:
setImmediate(()=> { console.log('timer1') Promise.resolve().then(function () { console.log('promise1') }) }) setTimeout(()=> { console.log('timer2') Promise.resolve().then(function () { console.log('promise2') }) }, 0) Node輸出: timer1 timer2 promise1 或者 promise2 timer2 timer1 promise2 promise1
按理說(shuō)
setTimeout(fn,0)
應(yīng)該比setImmediate(fn)
快,應(yīng)該只有第二種結(jié)果,為什么會(huì)出現(xiàn)兩種結(jié)果呢?這是因?yàn)镹ode 做不到0毫秒,最少也需要1毫秒。實(shí)際執(zhí)行的時(shí)候,進(jìn)入事件循環(huán)以后,有可能到了1毫秒,也可能還沒(méi)到1毫秒,取決于系統(tǒng)當(dāng)時(shí)的狀況。如果沒(méi)到1毫秒,那么 timers 階段就會(huì)跳過(guò),進(jìn)入 check 階段,先執(zhí)行setImmediate的回調(diào)函數(shù)。
另外,如果已經(jīng)過(guò)了Timer階段,那么setImmediate會(huì)比setTimeout更快,例如:
const fs=require('fs'); fs.readFile('test.js', ()=> { setTimeout(()=> console.log(1)); setImmediate(()=> console.log(2)); });
上面代碼會(huì)先進(jìn)入 I/O callbacks 階段,然后是 check 階段,最后才是 timers 階段。因此,setImmediate才會(huì)早于setTimeout執(zhí)行。
具體可以看《Node 定時(shí)器詳解》。
5.2 不同異步任務(wù)執(zhí)行的快慢
setTimeout(()=> console.log(1)); setImmediate(()=> console.log(2)); Promise.resolve().then(()=> console.log(3)); process.nextTick(()=> console.log(4)); 輸出結(jié)果:4 3 1 2或者4 3 1 2
因?yàn)槲覀兩衔恼f(shuō)過(guò)microTask會(huì)優(yōu)于macroTask運(yùn)行,所以先輸出下面兩個(gè),而在Node中process.nextTick比Promise更加優(yōu)先[3],所以4在3前。而根據(jù)我們之前所說(shuō)的Node沒(méi)有絕對(duì)意義上的0ms,所以1,2的順序不固定。
5.3 MicroTask隊(duì)列與MacroTask隊(duì)列
setTimeout(function () { console.log(1); },0); console.log(2); process.nextTick(()=> { console.log(3); }); new Promise(function (resolve, rejected) { console.log(4); resolve() }).then(res=>{ console.log(5); }) setImmediate(function () { console.log(6) }) console.log('end'); Node輸出:2 4 end 5 1 6
這個(gè)例子來(lái)源于《JavaScript中的執(zhí)行機(jī)制》。Promise的代碼是同步代碼,then和catch才是異步的,所以4要同步輸出,然后Promise的then位于microTask中,優(yōu)于其他位于macroTask隊(duì)列中的任務(wù),所以5會(huì)優(yōu)于1,6輸出,而Timer優(yōu)于Check階段,所以1,6。
綜上,關(guān)于最關(guān)鍵的順序,我們要依據(jù)以下幾條規(guī)則:
同一個(gè)上下文下,MicroTask會(huì)比MacroTask先運(yùn)行
然后瀏覽器按照一個(gè)MacroTask任務(wù),所有MicroTask的順序運(yùn)行,Node按照六個(gè)階段的順序運(yùn)行,并在每個(gè)階段后面都會(huì)運(yùn)行MicroTask隊(duì)列
同個(gè)MicroTask隊(duì)列下process.tick()會(huì)優(yōu)于Promise
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。