iT邦幫忙

0

更新網站前端內容, 如可不影響正在瀏覽網站的使用者體驗

  • 分享至 

  • xImage

如果有個網站24小時都有人在使用, 沒有明顯的尖峰或離峰時段, 假如想更新前端的javascript的部份, 因為js會呼叫後端某個web api, 所以當這個api做了一些修改, 比如需要傳入的參數有所變動, 故前端的js也要配合調整。假如現在已經有某個使用者在線上, 他瀏覽器載入的是更新前的js, 而我現在一但做了更新, 假設我更新的這段時間他始終都沒有離開目前的頁面, 那麼他在頁面上觸發了js並呼叫api (js傳舊的參數格式), 但此時的api所接受的參數已經跟先前不一樣了, 所以造成錯誤。所以這種問題有什麼辦法處理?

我想到的解法: 後端appi返回error到前端, 前端js做相對應的處理, 比如顯示: 很抱歉, 系統更新, 請重新登入 (或是自動導到首頁讓他重新再進到他原本所在的頁面來更新裡面的js程式, 或是用js來自動"強制"刷新當前的頁面達到重新下載新的js)

雖然這樣還是會讓使用者有些不方便, 但至少有做正確的回應, 否則js的出錯將導致頁面無任何反應, 使用者反而不知道發生什麼事了, 因為怎麼按按鈕, 網頁沒有動靜。

不知大家有何想法, 謝謝

看更多先前的討論...收起先前的討論...
黃彥儒 iT邦高手 1 級 ‧ 2022-05-03 12:19:23 檢舉
是什麼原因讓你沒辦法維護兩個不同版本的API短短幾天呢?
froce iT邦大師 1 級 ‧ 2022-05-03 13:10:04 檢舉
現在web api的框架通常能讓你同時保持多個版本。
WILL.I.AM iT邦新手 3 級 ‧ 2022-05-03 13:40:49 檢舉
假如原api只有一個參數, url如 xxxx/getInfo?userId=123

如果今天有兩件事要做, 一是發現原api有一個bug, 二是想再增加參數, 例如 xxxx/getInfo?userId=123&foo=abc

所以我想棄用原本的api, 也就是不要花時間去修改它的bug, 反正api也還要再多加一個參數, 就乾脆重新寫一個2個參數版本的新api並使用它

如果依照你們的建議, 同時留保這兩個版本的api, 即使舊的已不符合現在的需求了, 但為了要讓前端不發生問題, 我還是得去修改舊api的bug嗎? 等到過一段時間後, 再移除舊的api, 你們的做法是這樣嗎?

如果你們認為這樣比較好, 那請過一般要過多久, 才適合刪掉不要的api? 有參考的時間嗎? 比如三天, 五天之後類的? 謝謝
Bochin iT邦新手 4 級 ‧ 2022-05-03 13:56:57 檢舉
如果只是後端api 參數不同,不能寫個Overload來解決嗎?如果變動已經很大,那我不懂堅持不重整網頁的理由在哪裡?
WILL.I.AM iT邦新手 3 級 ‧ 2022-05-03 14:31:10 檢舉
@Bochin , 沒有堅持不重整網頁~~ 可能我原文內容太多, 沒讓你看懂我描述的情境, 我再更具體舉例好了。如果使用者正在瀏覽某一頁面, 該頁面有個js的function會呼叫api, 並且帶一個參數。重點來了, 在使用者還停留在這個頁面的期間, 我更新了系統, 並且這個api變成需要兩個參數了, 但user眼前的頁面是在我更新系統前就載入的, 所以他的頁面上的js 呼叫的api依然是只帶一個參數, 此時他若觸發呼叫, 則會出錯, 因為實際上這個api已經變成需要兩個參數了。
所以我才有說明是不是後端要return error以便前端js可以處理導頁到首頁讓他重新進來或刷新當前的頁面, 以便載入新的js的function內容(也就是更新成js call api帶兩個參數的版本)

當然可以overload啊, 你看我在2022-05-03 13:40:49有回覆, 就是提到overload的作法, 但我也說明了一些情況, 考慮這種情況有無必要overload, 因為其中一種方式已經不再需要了
Zed_Yang iT邦新手 3 級 ‧ 2022-05-03 16:04:28 檢舉
1.Token時間過期,前端會強制登出,讓User重新登入,也能取得新的js打新的api url
2.尚未過期,只剩下新的url可以打通(增加參數),故原始的api回傳錯誤給前端判斷,強制User Reload頁面取得新的js
至於判斷到錯誤的api url,前端要如何提醒User甚麼訊息,就看你們如何規劃
WILL.I.AM iT邦新手 3 級 ‧ 2022-05-03 16:19:31 檢舉
@Zed_Yang
你提到的第1點, 我沒這方面的問題, 因為重新登入本來就不會有問題。
你提到的第2點, 這完全就是我在原文中我想到的解法
designer iT邦新手 5 級 ‧ 2022-05-04 20:26:52 檢舉
過度期期間藏一個iframe到網頁裡面,等更新完(以最久連續使用者為主)之後再移除。
iframe可以做很多事。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
0
bizpro
iT邦大師 1 級 ‧ 2022-05-03 13:58:41

建議:

  1. 首先要有一個定期檢查伺服器API更新狀態的javascript腳本, 可以用async做long polling, 或直接用setInterval. 我通常用XMLHttpRequest來檢查. 或者就直接用一個API來定期檢查.(XMLHttpRequest就是jQuery的AJAX底層, 我不用jQuery)
  2. 用document.getElementByTagName('script')找出所有的script元件. 用迴圈一一檢查那一個外部的js檔, 或是嵌入的腳本需要替換.檢查的邏輯依您自己的需求.
  3. 如果是外部的js檔, 用<script元件>.parentNode.replaceChild(<新的js url>, <script元件>)
  4. 如果是嵌入的script, 直接用innerHTML替換.

關鍵在步驟3, 我常用parentNode來處理動態元件, 您可參考,
http://www.javascriptkit.com/javatutors/loadjavascriptcss2.shtml
https://javascript.info/long-polling

看更多先前的回應...收起先前的回應...
WILL.I.AM iT邦新手 3 級 ‧ 2022-05-03 14:34:54 檢舉

不知道您是否有詳細看過我的問題? 我想您可能誤解了, 但還是謝謝您

bizpro iT邦大師 1 級 ‧ 2022-05-03 15:01:14 檢舉

假如想更新前端的javascript的部份, 因為js會呼叫後端某個web api, 所以當這個api做了一些修改, 比如需要傳入的參數有所變動, 故前端的js也要配合調整。

沒錯啊. 要動態改變前端Javascript來配合修正後端API參數. 也就是要動態修正實體DOM.

WILL.I.AM iT邦新手 3 級 ‧ 2022-05-03 16:13:20 檢舉

我懂你的意思了, 雖然感覺有一點工程浩大, 我也許暫時不會用這種做法, 不過這也是一種思路, 謝謝分享

bizpro iT邦大師 1 級 ‧ 2022-05-03 16:54:46 檢舉

不會工程浩大, 就幾十行程式碼吧, 但這是正路. 我有一個案子是這樣做的. 只是不是修正API, 但還是動態修正實體DOM中的Javascript.

WILL.I.AM iT邦新手 3 級 ‧ 2022-05-03 22:33:57 檢舉

應該說, 我本來只是想單純解決一個頁面呼叫api的問題, 但若採用你這種方式, 就變成是影響到整個網站, 影響範圍一下就變這很大, 這樣值得嗎? 想必是需要通盤思考是否要這麼做。

此外, 一但這麼做的話, 大量的使用者從瀏覽器上的頁面對伺服器發出long polling 或 setInterval, 這對server來說, 會是不小的效能負擔。是不是本末倒置了呢?

bizpro iT邦大師 1 級 ‧ 2022-05-04 11:24:33 檢舉

您的需求本來就是long polling. 而我提的方案是stateless, 基本上對server的負擔很輕微, 但是不是會對server造成負擔,要看:

  1. server端的檢核邏輯與處理方式, 建議用redis來處理或其他cache的方式, 降低session的存在時間, 不要用一般資料庫.
  2. 併發的數量, 如果是用Nginx, 超高併發是沒有問題的, IIS的效能也很好,
  3. polling的頻率: 這牽涉到使用者經驗與服務水準.
    由於您的需求(本)是stateless的long polling, 如果不是要用long polling處理, 那就是不同的需求, 例如, server端檢核出API的差異, 送回API錯誤訊息, 請使用者刷新頁面重送, 或用我建議的2與3步驟直接修改實體的DOM.
bizpro iT邦大師 1 級 ‧ 2022-05-04 14:50:23 檢舉

以reactive的方式取代long polling:

  1. 在同一個funcation中, 當Server回傳API錯誤訊息, 啟動修正API程序.
  2. 用document.getElementByTagName('script')找出所有的script元件. 用迴圈一一檢查那一個外部的js檔, 或是嵌入的腳本需要替換.檢查的邏輯依您自己的需求.
  3. 如果是外部的js檔, 用<script元件>.parentNode.replaceChild(<新的js url>, <script元件>)
  4. 如果是嵌入的script, 直接用innerHTML替換.
0
天黑
iT邦研究生 5 級 ‧ 2022-05-03 16:18:04

可以考慮,新舊並行一段時間,接著有要上板再拿掉舊的,這樣就可以確保新跟舊都沒問題

0

基本來說,如果你這個問題比較難處理。
難處理的原因是,無法了解你的情境是如何的。

正常一般來說,直接更換到JS的程式碼的可能性不大。
並不是沒辦法處理,而是處理了會有安全性隱憂。
大多數而言,還是會去做判斷直接重刷頁面為主。

正規來說,你會想要變程式碼的原因。不外乎是因為變數值建立到對應的JS程式碼。
而其JS程式碼是由後端生成出來的。(目前我猜測是這樣,猜錯請見諒)

但目前的網頁寫法,能不動JS主程式碼就不動。變數值還是會利用請求的方式回傳。
這樣就不容易發生改後端要連動前端一起改。

不過我不清楚你碰到的情境是如何的。就目前而言,你說的判斷後重刷頁面或是重新登入,算是比較安全的做法。

我要發表回答

立即登入回答