登錄是一項核心基礎功能,通過登錄對用戶進行唯一标識,繼而才可以提供各種跟蹤服務,如收藏、下單、留言、消息、發布、個性化推薦等。小程序功能的方方面面大多會直接/間接涉及登錄,因而,登錄功能健壯與否高效與否是值得重點關注與保障的。
登錄涉及的面比較多:觸發場景上,各種頁面各種交互路徑都可能觸發登錄;交互過程上,既需要用戶提供/證明id,也需要後端記錄維護,還需要保證安全性;複用場景上,既是通用功能,需要多場景多頁面甚至多小程序複用,又是定制功能,需要各場景/頁面/小程序區分處理。要做到各種情形下都有良好的交互體驗,且健壯、高效、可複用、可擴展、可維護,還是相對比較複雜的。
本文将探讨小程序登錄過程中的一些主要需求和問題,以漸進叠代的方式提出并實現一個健壯、高效的登錄方案。
順帶一提,es6語法中的async/await、Promise、decorator等特性對于複雜時序處理相當有增益,在本文中也會有所體現。
基礎流程
如上圖所示,基礎登錄流程為:
該流程主要基于以下考慮:
拒絕授權問題
問題:
獲取微信用戶信息時,會出現一個授權彈窗,需要用戶點擊“允許”才能正常獲取;
若用戶點擊“拒絕”,不僅當次登錄會失敗,一定時間内後續登錄也會失敗,因為短期内再次調用微信用戶信息接口時,微信不會再向用戶展示授權彈窗,而是直接按失敗返回。
這樣導緻用戶隻要拒絕過一次,即使後來對小程序感興趣了願意授權了,也難以再次操作。
方案:
如上圖所示,增加以下流程以處理拒絕授權問題:
這樣,用戶拒絕授權隻會影響本次登錄,不至于無法進行下次嘗試。
登錄态過期問題
問題:
上圖截自微信官方文檔,從中可以看出:
此外,實踐中發現,wx.checkSession平均耗時約需200ms,每次接口調用前都先檢查一遍,開銷還是蠻大的。
如何既保證接口功能正确有效,又不用每次耗費高額的查詢開銷,成為了一個問題。
方案:
如上圖所示,增加以下流程以處理登錄态過期問題:
這樣,隻有在真正需要重新登錄的時候(無前端登錄态/後端登錄态失效/後端被提示微信登錄态失效)才會重新執行登錄流程;并且,一旦需要重新登錄,就會自動重新觸發登錄流程。
并發問題
問題:
如上圖所示,頁面各組件各功能有可能同時觸發登錄流程,可能會導緻:
方案:
如上圖所示,加入免并發邏輯:若登錄流程正在進行,則不重複觸發登錄流程,而是加入當前流程的監聽隊列,待登錄結束時再一并處理。這樣,任一時刻最多隻有一個登錄流程正在進行。
流程實現時序控制
如上圖所示,目前登錄流程已較為複雜,步驟較多,且大多是異步操作,每步成功失敗需要區分處理,處理過程又會相互交織。如果直接在微信接口/網絡接口提供的success/fail回調中進行邏輯處理,會造成:
因而采用Promise async/await進行時序管理:
将每個步驟Promise化:
使用async/await管理整體時序:
如以上代碼所示,微信登錄、獲取微信用戶信息、提示授權、打開權限面闆等每一步都是異步操作,都要等待success/fail回調才能獲得操作結果并發起下一個操作;但利用Promise async/await,可以像普通流程一樣,将這些操作線性組合,順序處理。
這樣,就可以實現直觀清晰的時序管理了。
過期處理
如以上代碼所示,單獨封裝一個requestWithLogin函數,在數據請求前後加入登錄态處理邏輯,可以保證數據請求會在有後端登錄态時被發送/重新發送。
并且,重新登錄過程對數據接口調用方是完全透明的,調用方隻需要知道自己的接口需不需要登錄态,而無需進行任何登錄态相關判斷處理,重登錄過程也不會對接口調用返回結果造成任何影響。
這樣,就可以實現登錄态過期自動重新登錄了。
并發控制
如以上代碼所示,利用Promise可以被多次then/catch的特性(亦即,一個async函數調用結果可以被await多次),可以使用一個Promise來記錄當前登錄流程,後續調用直接對該Promise進行監聽。
這樣,就可以實現登錄流程免并發了。
至此,我們就得到了一個功能可用、相對健壯、相對高效的登錄模塊。但依然還是存在優化空間的。
場景優化二次授權問題
問題:
用戶同意授權後,小程序可以訪問到微信用戶信息,并且一段時間内再次訪問時,也不會重新出現授權彈窗;
但是,如果用戶長時間未使用小程序,或将小程序删除重進,則登錄時會再次出現授權彈窗。
一方面會對用戶造成幹擾,影響其浏覽效率;另一方面,不利于流失用戶召回。
方案:
再次授權場景其實并不是很必要:
因而,增加以下流程以優化二次授權場景:
如上圖所示,在微信登錄接口調用成功之後,先嘗試直接根據openid完成登錄過程,若失敗再去請求用戶授權。
這樣,隻有新用戶才會出現授權彈窗;老用戶、回歸用戶,都可以直接靜默完成登錄過程。
場景适配問題
問題:
不同場景對登錄行為可能有不同的期望:
單一的登錄流程很難滿足這種多元的場景需求。
方案:
調用登錄/要求登錄的數據接口時支持指定場景模式:
如上圖所示,登錄流程支持指定不同場景模式:
實現
場景優化方案主要是增加了一些流程&判斷,使用上文中的“時序控制”基本可以解決。
主要難點在于,上文中的免并發機制不再适用。比如,靜默模式正在進行時又觸發了一個強制模式的請求,此時,應觸發授權彈窗正常登錄而不是監聽使用靜默模式的登錄結果。
如果拆成每個模式各自免并發,一方面,登錄流程需重複書寫,不便複用;另一方面,模式之間并發也存在風險。
因而,引入公共步驟并合機制:
如以上代碼所示,将登錄免并發改為每個公共步驟免并發,登錄流程中就可以根據場景模式自由地進行步驟管理。
這樣,就可以實現對不同登錄場景進行定制化支持。
效果示例
簡潔起見,以下代碼使用wepy框架寫法,原生小程序/其它框架可類似參考。
如以上代碼所示,可以做到老用戶/回歸用戶進入頁面時自動悄悄登錄,以提供更多個性化服務;新用戶進入頁面時不進行任何幹擾,直到進行留言等操作時才自動出現授權彈窗,且授權完成後自動完成該次行為,無需用戶再次操作。
并且,這些過程對業務代碼是完全透明的,業務代碼隻需要知道自己調用的接口是 必須登錄/最好登錄/必須第一次調用就登錄/不用登錄,并相應地指定 mode=common/silent/force/不使用requestWithLogin,即可。
這樣,我們的登錄模塊可以在不同場景指定不同登錄邏輯,從而支持設計實現更多元更精細更流暢的登錄交互。
界面優化
問題:
獲取微信用戶信息時,直接出現系統授權彈窗有時候是很突兀的;使用自定義授權界面和價值文案進行引導,得當的話可以有效提高授權成功率。
而且,從10月10号起,小程序将不再支持自動彈窗授權用戶信息和自動打開權限面闆,這兩種操作必須使用<button>組件由用戶主動觸發。彼時起,自定義界面将不再是優化,而會是必需。
這意味着登錄過程必須與頁面dom耦合,之前的純js邏輯不再适用。
方案1:登錄浮層
在所有頁面放置登錄浮層,頁面需要登錄時則調起該浮層,經由浮層按鈕完成授權及後續流程。
實現
授權浮層AuthModal.wpy:
登錄模塊login.js:
如以上代碼所示,雖然自定義浮層需要展示按鈕、等待用戶點擊、處理點擊、考慮用戶不點擊直接返回,交互流程相對複雜,但依然可以利用Promise使交互細節對外透明。打開浮層時返回一個Promise,在各個交互出口對Promise進行resolve,則使用時隻需将其作為一個普通的異步過程對待。
這樣,就可以實現無縫接入自定義浮層授權。
方案2:獨立登錄頁
需要授權用戶信息時,跳轉至一個專門的登錄頁面,頁面中展示引導内容和授權<button>,用戶操作完畢後再自動返回先前頁面。
實現
授權全局數據模塊userAuthHub.js:
登錄模塊login.js:
登錄頁login.wpy:
如以上代碼所示,雖然授權過程需要進行跨頁面交互,但利用Promise和小程序代碼包特性,可以在前一頁面設置監聽,登錄頁面進行回調。登錄頁面交互結束後,前一頁面會自動繼續執行登錄流程,調用方無需進行返回刷新等額外處理,數據接口也會繼續調用,用戶無需再次操作。
這樣,就可以實現無縫接入跨頁面授權交互。
兩種方案都可以實現自定義授權界面。内嵌浮層會增加一定維護成本和少量資源開銷,但可以直接在當前頁面完成登錄交互,頁面自定義空間也相對更大;獨立登錄頁會來回跳轉犧牲一定的交互體驗,但可以把登錄所需dom元素集中在登錄頁,減少維護成本和頁面侵入。二者各有優劣,可以按需采用或混合使用。
這樣,我們的登錄模塊可以使用自定義授權界面,從而支持設計實現更雅觀更精緻的授權引導。
複用優化多小程序間複用&定制
問題:
開發方可能同時維護着多個小程序,這些小程序使用着相同的後端接口和後端用戶體系,又有着各自的小程序标識和使用訴求。
一方面,希望登錄模塊可以統一維護,不需要每個小程序各自開發;另一方面,又希望各小程序可以進行差異化定制,包括小程序前端标識不一緻等剛性差異,和授權提示文案、埋點、授權交互等個性差異。
方案&實現:
1、統一流程 個性化配置
2、公共&默認流程由登錄模塊統一維護,各小程序直接複用;差異流程支持各小程序以配置的形式自定義擴展&覆蓋。
3、配置檢查
引入配置過程會存在一個潛在風險:觸發登錄時,小程序尚未完成登錄模塊配置。
理論上,隻要全局都使用同一個登錄實例并在app.js頂部進行配置,應該就沒有這樣的時序風險。但複用方是不會自覺的,不一定會使用同一個實例,配置過程也不一定會被放在頂部,甚至有可能被放在某些異步數據返回之後。因而登錄模塊隻導出唯一實例并加入配置檢查環節以保證該邏輯健壯性:
這樣,就可以實現在多個小程序間複用登錄模塊,由登錄模塊統一維護整體時序和默認流程,同時支持各小程序進行差異性定制&擴展。
多頁面間複用&定制
問題:
不同頁面對登錄過程有時也存在定制需求,比如授權引導文案,有些頁面可能希望提示“授權後可以免費領紅包”,有些頁面可能是“授權後可以為好友助力”/“授權後可以獲得智能推薦”/... 諸如此類。
方案&實現:
在頁面中設置鈎子供其提供個性化配置。
頁面xxx.wpy:
小程序級登錄配置:
這樣,就可以實現所有頁面共用登錄模塊的同時,支持每個頁面進行定制化修改。
這樣,我們的登錄模塊可以在多小程序、多頁面中複用,并支持各小程序、各頁面進行差異性定制。從而實現更好的可維護性可擴展性:
本文摘自微信公衆号大轉轉FE,由編碼之道編輯整理
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!