在bash
命令或npm script
中使用&
來實現併發
效果時,其實是把&
左側的命令丟入後臺運行,右側剩餘命令看作 總體 任務在前臺運行,以此來實現併發效果。javascript
而&&
是串行執行兩側命令,先執行完左側後再執行右側。java
切記!!!node
command1 & command2 && command3
複製代碼
並非併發執行command1
和command2
後再執行command3
git
而是併發執行command1
和command2 && command3
github
最近,我組在遠端構建組內sdk
時踩了個坑!!!原先咱們是ci
構建好sdk,推送到服務器上,發現常常會出現推過去的zip
包文件不全,或者文件全了可是文件的內容不全。非常神奇。shell
排查一番後發現,咱們package.json
中的scripts
寫了個大概以下的命令npm
cross-env npm run build-core & npm run build-ui
複製代碼
並把這個命令用 npm run build
代替。json
嗯~看着沒問題,並行
的構建sdk-core
以及sdk-ui
。bash
構建好後就應該是打包,咱們卻在ci
裏面寫了個「致命」的命令服務器
npm run build && node publish.js
複製代碼
publish.js
就是咱們用來發布到的腳本文件。看上去也是沒問題。。可是細想一下,整個命令就變成了這樣
cross-env npm run build-core & npm run build-ui && node publish.js
複製代碼
這裏就踩到了一個坑!!!!
咱們原來是想先並行的構建ui
與core
,完成後執行上傳腳本。。可是這裏卻變成了並行
執行下面兩件事
1. 構建core
2. 構建ui和發佈
複製代碼
這裏咱們能夠粗略地理解爲&&
的優先級更高因此致使了這種現象。
但實際上是bash
中&
命令的特殊性致使的,前面我對「並行」作了特殊高亮,是由於表現上是並行的,可是&
命令的含義並非並行的執行任務。
&
命令的真實含義是把左側的任務當即進入後臺執行,這樣就是實現了&
兩側任務同時併發執行的效果,實際上會致使上面說的不符合指望的緣由並非由於優先級問題,按咱們的理解&
做爲運算符的話優先級是高於&&
的,之因此會形成上面的緣由是由於命令按順序執行的話,&
使得左側任務瞬間進入後臺執行,右側剩餘命令就看作一個總體任務了。
準備好4個文件index1.js
,index2.js
,index3.js
以及package.json
。
內容分別以下
index1.js
console.log('start index1');
setTimeout(() => {
console.log('end index1');
}, 6000);
複製代碼
index2.js
console.log('start index2');
setTimeout(() => {
console.log('end index2');
}, 3000);
複製代碼
index3.js
console.log('start index3');
setTimeout(() => {
console.log('end index3');
}, 500);
複製代碼
package.json
{
"name": "npm-script",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"test":"node index1.js & node index2.js && node index3.js"
}
}
複製代碼
接着咱們運行npm test
。
神奇的事情發生了!!!
node index1.js & node index2.js && node index3.js
複製代碼
錯誤的理解上面的執行順序的話,指望結果應該是在index1
和index2
結束後纔開始index3
,實際輸出否決了這個想法。
那把&
當作並行運算符而&&
的優先級更高的話,結果應該是就是index3
是在index2
後開始,而index1
和index2
是並行開始,看上面的圖確實很像,但有個神奇的地方是,終端已經輸出done
了,退出了,過了一會纔再次輸出end index1
!!
確實很神奇,但結合上面說的&
的原理就能理解。
先把index1
扔到後臺執行,當前終端執行&
右邊的命令,跑完index2
後跑index3
,而後結束當前終端,此時在後臺的index1
可能還沒執行完。這樣就形成了圖示現象。