2021年7月15日 星期四

練習作文:SSR 原理,以 Next.js 為例

 最近面試蠻容易遇到,大家都用框架也沒可能自己費工刻一個,因此練好作文說得一口好 SSR(Server Side Rendering) 還是需要練習一下。

一開始用 HTML 寫網頁的模式就是 CSR(Client Side Rendering),在 Client 端開始解析 JS,建立 DOM,隨著頁面漸漸著重於 JS,以及前端框架興起的 SPA (Single Page Application),提供了利用 Router 迅速切換頁面的優良體驗,但是這樣的模式帶來了幾個缺點,第一個是整包的 JS 載入十分花費效能,第二是一整包的 JS 爬蟲無法解析出 HTML 內容,不利 SEO,因此 React 發展出 Next , Vue 發展出 Nuxt ,SSR 架構 Server Side 會回傳整個 HTML,並且在各個頁面重新呼叫 Request,避免初次載入整包 JS 造成效能問題,在一個產品的越後期要改成成 SSR 架構就越艱難,因此最好是早期就訂好 SEO 需求,決定架構是否採用 SSR 。



參考資料:Next文件









2021年7月11日 星期日

Vue 與 React 生命週期比較

以 Vue 3 與 React 做比較

建立實體:

Vue:

const vm = Vue.createApp({

data(){

return{

name:'Jeff'

}

}

})

vm.mount('#app')

React:

ReactDOM.render(

  <h1>Hello, world!</h1>,

  document.getElementById('root')

);

初始化:
Vue:
setup()

React:
componentDidMount()

React 會 render 畫面兩次,並只顯示後一次 render 出來的結果,起始資料可以再這邊 call API。

更新畫面:
Vue:
onUpdated()

React:

componentDidUpdate()


React 的首次 render 不會觸發 DidUpdate

結束:
Vue:
onUnmounted()

React:
componentWillUnmount()

React 16.8之後狀態管理改用 Hook ,具有比生命週期更為直覺且省去複雜的 this,轉向 function component 為主的建置。



參考資料:

Vue

React

2021年7月8日 星期四

leetCode Missing Number

 最近因為面試解了不少前測,爬文章的時候看到這題有蠻多想法的, leetCode 會計算花費的運算時間覺得有趣,就研究了一下。

題目是 0~N 的整數陣列,中間缺了哪一個數?

一開始想到用排好再計算差值的方法

 const array = [301];
 const missnumber = nums => {
        array
          .sort((a, b) => a - b)
          .map((item, index) => item - array[index - 1])
          .find(item => item > 1);
        return missnumber;
      };
missnumber(array)

覺得有點多行,感覺應該有什麼很酷的方法不用反覆對陣列操作,就找了一下,發現可以用XOR 運算。

原理是 a ^ b ^ c ^ a ^ b = a ^ a ^ b ^ b ^ c = 0 ^ 0 ^ c = c

 const array = [301];
 const missNumber = nums => {
        const nArray = [];
        for (let i = 0; i < nums.length + 1; i++) {
          nArray.push(i);
        }
        const mathArray = nums.concat(nArray);
        const outputNumber = mathArray.reduce((total, e) => total ^ e);
        return outputNumber;
      };
 missNumber(array);

於是改了一種寫法,就程式的行數而言下面比較長,效能而言由於我家網路莫名其妙,兩者互有快慢比不出來,未來要仔細研究一下時間複雜度的計算。

參考資料:https://www.ruanyifeng.com/blog/2021/01/_xor.html










2021年7月2日 星期五

Fisher-Yates Shuffle 亂數排序演算法

被問到亂數排序的問題,之前都只是會用 Math.random() ,用陣列方法排一排之類的,沒在認真思考最有效率的排法。
有一個很瀟灑的寫法:

     array.sort((a, b) => Math.random() - 0.5);

可惜經過實測,不知為何會有機率分配不均的問題,因此才往下看 Fisher-Yates Shuffle。
原理是將陣列由後往前每次與前方隨機一個元素交換位置,這樣實測結果會是差不多的,沒看過也不太容易想出合理的解,或變得要用小樣本去執行幾萬次做測試,平常不太容易會接觸到,紀錄一下。


 const fisherYatesShuffle = array => {
        for (let i = array.length - 1; i > 0; i--) {
          let x = Math.floor(Math.random() * [i + 1]);
          [array[i], array[x]] = [array[x], array[i]];
        }
      };



參考資料:

[筆記] 如何正確實作 JavaScript Array Random Shuffle 亂數排序演算法

2021年7月1日 星期四

更新 Promise 的範例

 最近接觸到不少 Promise 操作,早期抄的一些範例也已經不合時宜不易讀,因此重寫一下理解。

創造一個 Promise 物件:

new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log("a"), resolve("a");
          }, Math.floor(Math.random() * 5* 1000);
        });

用 setTimeout 做出時間差,模擬真正 API 回來時間差的情境;

Promise 物件有三種狀態:pending(等待),fulfilled(已完成),rejected(已失敗);

Promise 物件有 resolve 與 reject 兩種回傳,resolve 是成功,reject 是失敗;

當串聯操作的時候,有幾種情況要考慮:需不需要照順序執行?需不需要依序得到結果?

先創造範例 a,b,c 三個 function

  const a = () => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log("a"), resolve("a");
          }, Math.floor(Math.random() * 5* 1000);
        });
      };
      const b = () => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log("b"), resolve("b");
          }, Math.floor(Math.random() * 5* 1000);
        });
      };
      const c = () => {
        return new Promise((resolve, reject) => {
          setTimeout(() => {
            console.log("c"), resolve("c");
          }, Math.floor(Math.random() * 5* 1000);
        });
      };

照順序執行:

console.log(a().then(b()).then(c()))

直接用 .then 或 .catch 可以按順序執行。不過 return 的順序則不一定。

依序得到結果:

  const enter = async () => {
        const cc = await c();
        const bb = await b();
        const aa = await a();
      };
      console.log("c->b->a"enter());

透過 ES6 async await ,使每個 Promise 得到結果才執行下一個,由於這樣一串時間會拖很長,務必將 function 與主要組件拆開,避免主要畫面轉圈圈轉不完。

整個都綁在一起不怕一個錯就全都跳錯,或是針對裡面的 Promise 物件錯誤有調整 resolve 的話,也可以用 Promise.all 來進行處理。

這個範例應該複製貼上都跑得了,也可以觀察 return 的順序,如有錯誤還請不吝指教。