微信小程序登錄方案_第1頁
微信小程序登錄方案_第2頁
微信小程序登錄方案_第3頁
微信小程序登錄方案_第4頁
微信小程序登錄方案_第5頁
已閱讀5頁,還剩11頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

微信?程序登錄?案登錄是?項核?基礎(chǔ)功能,通過登錄對?戶進?唯?標(biāo)識,繼?才可以提供各種跟蹤服務(wù),如收藏、下單、留?、消息、發(fā)布、個性化推薦等。?程序功能的?????多會直接/間接涉及登錄,因?,登錄功能健壯與否?效與否是值得重點關(guān)注與保障的。登錄涉及的??較多:觸發(fā)場景上,各種頁?各種交互路徑都可能觸發(fā)登錄;交互過程上,既需要?戶提供/證明id,也需要后端記錄維護,還需要保證安全性;復(fù)?場景上,既是通?功能,需要多場景多頁?甚?多?程序復(fù)?,?是定制功能,需要各場景/頁?/?程序區(qū)分處理。要做到各種情形下都有良好的交互體驗,且健壯、?效、可復(fù)?、可擴展、可維護,還是相對?較復(fù)雜的。本?將探討?程序登錄過程中的?些主要需求和問題,以漸進迭代的?式提出并實現(xiàn)?個健壯、?效的登錄?案。順帶?提,es6語法中的async/await、Promise、decorator等特性對于復(fù)雜時序處理相當(dāng)有增益,在本?中也會有所體現(xiàn)?;A(chǔ)流程如上圖所?,基礎(chǔ)登錄流程為:調(diào)?微信登錄接?wx.login獲取微信登錄態(tài)調(diào)?微信?戶信息接?wx.getUserInfo獲取微信?戶信息調(diào)?后端登錄接?,根據(jù)微信?戶標(biāo)識及信息,記錄維護??的?戶體系該流程主要基于以下考慮:交互上,?戶只需在微信的授權(quán)彈窗上點擊確認,不需要輸?賬號密碼等復(fù)雜操作;體驗上,可以直接獲取微信昵稱頭像等作為初始?戶信息,使?起來更親切,傳播時好友辨識度也更?;開發(fā)上,可以直接使?或映射微信?戶標(biāo)識,?需??進?標(biāo)識的?成和驗證;安全上,微信已經(jīng)在?戶信息的獲取、傳輸、解密等環(huán)節(jié)做了許多處理,安全性相對有保障。健壯流程拒絕授權(quán)問題問題:獲取微信?戶信息時,會出現(xiàn)?個授權(quán)彈窗,需要?戶點擊“允許”才能正常獲??;若?戶點擊“拒絕”,不僅當(dāng)次登錄會失敗,?定時間內(nèi)后續(xù)登錄也會失敗,因為短期內(nèi)再次調(diào)?微信?戶信息接?時,微信不會再向?戶展?授權(quán)彈窗,?是直接按失敗返回。這樣導(dǎo)致?戶只要拒絕過?次,即使后來對?程序感興趣了愿意授權(quán)了,也難以再次操作。?案:如上圖所?,增加以下流程以處理拒絕授權(quán)問題:獲取微信?戶信息失敗時,判斷是否近期內(nèi)拒絕授權(quán)導(dǎo)致;若為拒絕授權(quán)導(dǎo)致,則提?并打開權(quán)限?板,供?戶再次操作;若?戶依然未授權(quán),則本次登錄失敗,否則繼續(xù)后續(xù)流程。這樣,?戶拒絕授權(quán)只會影響本次登錄,不?于?法進?下次嘗試。登錄態(tài)過期問題問題:微信登錄態(tài)有效期不可控上圖截?微信官??檔,從中可以看出:后端session_key隨時可能失效,什么時候失效開發(fā)者不可控;要保證調(diào)?接?時后端session_key不失效,只能在每次調(diào)?前先使?wx.checkSession檢查有效期或直接重新執(zhí)?微信登錄接?;前端不能隨便重新執(zhí)?微信登錄接?,可能導(dǎo)致正在進?的其它后端任務(wù)session_key失效;此外,實踐中發(fā)現(xiàn),wx.checkSession平均耗時約需200ms,每次接?調(diào)?前都先檢查?遍,開銷還是蠻?的。如何既保證接?功能正確有效,?不?每次耗費?額的查詢開銷,成為了?個問題。后端登錄態(tài)過期后端??的登錄態(tài)有效期也存在類似的問題,有可能在調(diào)?接?時才發(fā)現(xiàn)后端登錄態(tài)已過期。?案:如上圖所?,增加以下流程以處理登錄態(tài)過期問題:調(diào)?數(shù)據(jù)接?時顯式指明是否需要登錄態(tài),若需要則在接?調(diào)?前后?動加?登錄態(tài)校驗邏輯;接?調(diào)?前只校驗前端登錄態(tài),不校驗后端登錄態(tài),也不校驗微信登錄態(tài),以節(jié)省每次校驗開銷;接?調(diào)?后校驗后端及微信登錄態(tài),若后端返回登錄態(tài)相關(guān)錯誤碼,則重置前端登錄態(tài)、重新登錄、重新調(diào)?數(shù)據(jù)接?。這樣,只有在真正需要重新登錄的時候(?前端登錄態(tài)/后端登錄態(tài)失效/后端被提?微信登錄態(tài)失效)才會重新執(zhí)?登錄流程;并且,?旦需要重新登錄,就會?動重新觸發(fā)登錄流程。并發(fā)問題問題:如上圖所?,頁?各組件各功能有可能同時觸發(fā)登錄流程,可能會導(dǎo)致:額外性能開銷,登錄流程重復(fù)進?,登錄接?重復(fù)調(diào)?;體驗問題,連續(xù)多次彈窗,影響?戶交互;邏輯問題,后?次登錄刷新了前?次登錄的session_key,導(dǎo)致前?次登錄接?解碼失敗,返回異常結(jié)果。?案:如上圖所?,加?免并發(fā)邏輯:若登錄流程正在進?,則不重復(fù)觸發(fā)登錄流程,?是加?當(dāng)前流程的監(jiān)聽隊列,待登錄結(jié)束時再?并處理。這樣,任?時刻最多只有?個登錄流程正在進?。流程實現(xiàn)時序控制如上圖所?,?前登錄流程已較為復(fù)雜,步驟較多,且?多是異步操作,每步成功失敗需要區(qū)分處理,處理過程?會相互交織。如果直接在微信接?/?絡(luò)接?提供的success/fail回調(diào)中進?邏輯處理,會造成:回調(diào)層層嵌套,影響代碼書寫和閱讀;不同路徑公共步驟難以統(tǒng)?提?。粫r序邏輯不直觀,不易管理。因??Promise+async/await進?時序管理:將每個步驟Promise化:classLogin{static_loginSteps={//各登錄步驟/***微信登錄:調(diào)?微信相關(guān)API,獲取?戶標(biāo)識(openid,某些情況下也能獲得unionid)*@return{Promise<Object>}微信?戶標(biāo)識*/wxLogin(){returnnewPromise((resolve,reject)=>{//結(jié)果以Promise形式返回wx.login({success(res){resolve(Object.assign(res,{succeeded:true}));//成功失敗都resolve,并通過succeeded字段區(qū)分},fail(res){resolve(Object.assign(res,{succeeded:false}));//成功失敗都resolve,并通過succeeded字段區(qū)分},})});},/***獲取微信?戶信息:調(diào)?微信相關(guān)API,請求?戶授權(quán)訪問個?信息*@return{Promise<Object>}微信?戶信息*/requestUserInfo(){returnnewPromise((resolve,reject)=>{//結(jié)果以Promise形式返回//...});},//...}}使?async/await管理整體時序:classLogin{staticasync_login(){//管理整體時序//letsteps=Login._loginSteps;//微信登錄letwxLoginRes=awaitsteps.wxLogin();if(!wxLoginRes.succeeded)//微信登錄接?異常,登錄失敗return{code:-1};//獲取微信?戶信息letuserInfoRes=awaitsteps.requestUserInfo();if(!userInfoRes.succeeded&&userInfoRes.failType==='userDeny'){//?戶近期內(nèi)曾經(jīng)拒絕授權(quán)導(dǎo)致獲取信息失敗awaitsteps.tipAuth();//提?授權(quán)l(xiāng)etsettingRes=awaitsteps.openSetting();//打開權(quán)限?板if(!settingRes.succeeded)//?戶依然拒絕授權(quán),登錄失敗return{code:-2};userInfoRes=awaitsteps.requestUserInfo();//?戶同意授權(quán),重新獲取?戶信息}if(!userInfoRes.succeeded)//其它原因?qū)е碌墨@取?戶信息失敗return{code:-3};//獲取?戶信息成功,進?后續(xù)流程//}}如以上代碼所?,微信登錄、獲取微信?戶信息、提?授權(quán)、打開權(quán)限?板等每?步都是異步操作,都要等待success/fail回調(diào)才能獲得操作結(jié)果并發(fā)起下?個操作;但利?Promise+async/await,可以像普通流程?樣,將這些操作線性組合,順序處理。這樣,就可以實現(xiàn)直觀清晰的時序管理了。過期處理classLogin{/***登錄*/staticasynclogin(options){if(Login.checkLogin())//若已有前端登錄態(tài),則直接按登錄成功返回return{code:0};//否則執(zhí)?登錄流程//...}/***普通數(shù)據(jù)請求,不進?登錄態(tài)檢查,結(jié)果以Promise形式返回*@param{Object}options參數(shù),格式同wx.request*@return{Promise}請求結(jié)果,resolve時為數(shù)據(jù)接?返回內(nèi)容,reject時為請求詳情*/staticasyncrequest(options){returnnewPromise((resolve,reject)=>{wx.request(Object.assign({},options,{success(res){resolve(res.data);},fail(res){reject(res);}});});}/***要求登錄態(tài)的數(shù)據(jù)請求,封裝了登錄態(tài)邏輯*@param{Object}options請求參數(shù),格式同wx.request*@param{Object}options.loginOpts登錄選項,格式同login函數(shù)*@return{Promise}返回結(jié)果,resolve時為數(shù)據(jù)接?返回內(nèi)容,reject時為請求詳情*/staticasyncrequestWithLogin(options){//先校驗/獲取前端登錄態(tài),保證?部分情況下請求發(fā)出時已登錄letloginRes=awaitLogin.login(options.loginOpts);if(loginRes.code!=0)thrownewError('loginfailed,requestnotsent:'+options.url);//發(fā)送數(shù)據(jù)請求letresp=awaitLogin.request(options);//若后端登錄態(tài)正常,則正常返回數(shù)據(jù)請求結(jié)果if(!Login._config.apiAuthFail(resp,options))//根據(jù)后端統(tǒng)?錯誤碼判斷登錄態(tài)是否過期returnresp;//若后端登錄態(tài)過期Login._clearLoginInfo();//重置前端登錄態(tài),保證后續(xù)再次調(diào)?login時會真正執(zhí)?登錄環(huán)節(jié)returnLogin.requestWithLogin(options);//重新登錄,重新發(fā)送請求,并將重新發(fā)送的請求的返回結(jié)果作為本次調(diào)?結(jié)果予以返回}}如以上代碼所?,單獨封裝?個requestWithLogin函數(shù),在數(shù)據(jù)請求前后加?登錄態(tài)處理邏輯,可以保證數(shù)據(jù)請求會在有后端登錄態(tài)時被發(fā)送/重新發(fā)送。并且,重新登錄過程對數(shù)據(jù)接?調(diào)??是完全透明的,調(diào)??只需要知道??的接?需不需要登錄態(tài),??需進?任何登錄態(tài)相關(guān)判斷處理,重登錄過程也不會對接?調(diào)?返回結(jié)果造成任何影響。這樣,就可以實現(xiàn)登錄態(tài)過期?動重新登錄了。并發(fā)控制classLogin{static_loginSingleton=null;//正在進?的登錄流程staticasync_login(){//登錄流程...}//封裝了免并發(fā)邏輯的登錄函數(shù)staticasynclogin(){if(Login._loginSingleton)//若當(dāng)前有登錄流程正在進?,則直接使?其結(jié)果作為本次登錄結(jié)果returnLogin._loginSingleton;//否則觸發(fā)登錄流程Login._loginSingleton=Login._login();//并在登錄結(jié)束時釋放并發(fā)限制Login._loginSingleton.then(()=>{Login._loginSingleton=null}).catch(()=>{Login._loginSingleton=null});//返回登錄結(jié)果returnLogin._loginSingleton;}}如以上代碼所?,利?Promise可以被多次then/catch的特性(亦即,?個async函數(shù)調(diào)?結(jié)果可以被await多次),可以使??個Promise來記錄當(dāng)前登錄流程,后續(xù)調(diào)?直接對該Promise進?監(jiān)聽。這樣,就可以實現(xiàn)登錄流程免并發(fā)了。?此,我們就得到了?個功能可?、相對健壯、相對?效的登錄模塊。但依然還是存在優(yōu)化空間的。場景優(yōu)化?次授權(quán)問題問題:?戶同意授權(quán)后,?程序可以訪問到微信?戶信息,并且?段時間內(nèi)再次訪問時,也不會重新出現(xiàn)授權(quán)彈窗;但是,如果?戶長時間未使??程序,或?qū)?程序刪除重進,則登錄時會再次出現(xiàn)授權(quán)彈窗。???會對?戶造成?擾,影響其瀏覽效率;另???,不利于流失?戶召回。?案:再次授權(quán)場景其實并不是很必要:?戶第?次授權(quán)時,開發(fā)者已經(jīng)可以獲得?戶昵稱、頭像等?戶信息和openid、unionid等?戶標(biāo)識;再次授權(quán)時,雖然?戶信息可能有更新,但完全可以等?戶進個?主頁/編輯信息時再進?同步,沒必要剛進?程序就彈窗;再次授權(quán)時,?戶標(biāo)識并不會變化;只調(diào)?微信登錄接?,不觸發(fā)授權(quán),已經(jīng)可以獲得openid了,通過openid就可以從數(shù)據(jù)庫中查找使?其上次授權(quán)時的?戶信息和unionid等其它?戶標(biāo)識。因?,增加以下流程以優(yōu)化?次授權(quán)場景:如上圖所?,在微信登錄接?調(diào)?成功之后,先嘗試直接根據(jù)openid完成登錄過程,若失敗再去請求?戶授權(quán)。這樣,只有新?戶才會出現(xiàn)授權(quán)彈窗;??戶、回歸?戶,都可以直接靜默完成登錄過程。場景適配問題問題:不同場景對登錄?為可能有不同的期望:有些場景,希望只在需要時?動登錄,如商品詳情頁,希望在?戶點擊留?、收藏等按鈕時?動調(diào)起登錄并完成留?、收藏等相應(yīng)操作;有些場景,希望只嘗試靜默登錄,如?頁,希望對?戶做個性化推薦和針對性投放,但?不愿彈窗阻撓?戶;有些場景,希望保證前后端登錄態(tài)?致,如微信接?數(shù)據(jù)解碼。單?的登錄流程很難滿?這種多元的場景需求。?案:調(diào)?登錄/要求登錄的數(shù)據(jù)接?時?持指定場景模式:如上圖所?,登錄流程?持指定不同場景模式:通?模式,為默認模式,會?動調(diào)起登錄并完成相應(yīng)數(shù)據(jù)請求和后續(xù)操作;靜默模式,只會嘗試靜默登錄,不會嘗試授權(quán)登錄,成功與否均不影響頁?功能和后續(xù)接?調(diào)?;強制模式,會重新登錄,不管前端是否保有登錄態(tài),以保證前后端登錄態(tài)同步。實現(xiàn)場景優(yōu)化?案主要是增加了?些流程&判斷,使?上?中的“時序控制”基本可以解決。主要難點在于,上?中的免并發(fā)機制不再適?。?如,靜默模式正在進?時?觸發(fā)了?個強制模式的請求,此時,應(yīng)觸發(fā)授權(quán)彈窗正常登錄?不是監(jiān)聽使?靜默模式的登錄結(jié)果。如果拆成每個模式各?免并發(fā),???,登錄流程需重復(fù)書寫,不便復(fù)?;另???,模式之間并發(fā)也存在風(fēng)險。因?,引?公共步驟并合機制:/***步驟并合修飾器,避免公共步驟并發(fā)進?*將公共步驟單例化:若步驟未在進?,則發(fā)起該步驟;若步驟正在進?,則監(jiān)聽并使?其執(zhí)?結(jié)果,?不是重新發(fā)起該步驟*/functionmergingStep(target,name,descriptor){letoriFunc=descriptor.value;letrunningInstance=null;descriptor.value=function(...args){if(runningInstance)//若步驟正在進?,則監(jiān)聽并使?其執(zhí)?結(jié)果,?不是重新發(fā)起該步驟returnrunningInstance;letres=oriFunc.apply(this,args);if(!(resinstanceofPromise))returnres;runningInstance=res;runningInstance.then(function(){runningInstance=null;}).catch(function(){runningInstance=null;});returnrunningInstance;}}classLogin{static_loginSteps={@mergingStep//步驟并合修飾器,避免公共步驟并發(fā)重復(fù)進?wxLogin(){returnnewPromise((resolve,reject)=>{//...});},@mergingStep//步驟并合修飾器,避免公共步驟并發(fā)重復(fù)進?asyncsilentLogin({wxLoginRes}){//...},...}staticasynclogin(options){////嘗試靜默登錄letsilentRes=awaitsteps.silentLogin({wxLoginRes});if(silentRes.succeeded){//靜默登錄成功,結(jié)束return{code:0,errMsg:'ok'};}if(options.mode==='silent')//靜默模式,只嘗試靜默登錄,不觸發(fā)授權(quán)彈窗;不管成功失敗都不影響頁?功能和后續(xù)接?調(diào)?return{code:0,errMsg:'loginfailedsilently'};//其它模式繼續(xù)嘗試授權(quán)登錄//...}}如以上代碼所?,將登錄免并發(fā)改為每個公共步驟免并發(fā),登錄流程中就可以根據(jù)場景模式?由地進?步驟管理。這樣,就可以實現(xiàn)對不同登錄場景進?定制化?持。效果?例簡潔起見,以下代碼使?wepy框架寫法,原??程序/其它框架可類似參考。importLoginfrom'../../lib/Login';exportdefaultclassextendswepy.page{asynconLoad(){//頁?初始化letdataRes=awaitLogin.requestWithLogin({//調(diào)?頁?數(shù)據(jù)接?url:'xxx/xxx',loginOpts:{mode:'silent'}//使?靜默模式,若為??戶/回歸?戶,會?動悄悄登錄,后端返回數(shù)據(jù)時可以包含?些個性化推薦;若為新?戶,也不會觸發(fā)彈窗,});//...}methods={asynconComment(){//?戶點擊了評論按鈕letaddRes=awaitLogin.requestWithLogin({//調(diào)?添加評論接?url:'xxx/addComment',data:{comment:'xxx'},loginOpts:{mode:'common'}//使?通?模式,若已登錄,會直接發(fā)送請求;若未登錄,會?動調(diào)起登錄并發(fā)送請求});//...}}}如以上代碼所?,可以做到??戶/回歸?戶進?頁?時?動悄悄登錄,以提供更多個性化服務(wù);新?戶進?頁?時不進?任何?擾,直到進?留?等操作時才?動出現(xiàn)授權(quán)彈窗,且授權(quán)完成后?動完成該次?為,?需?戶再次操作。并且,這些過程對業(yè)務(wù)代碼是完全透明的,業(yè)務(wù)代碼只需要知道??調(diào)?的接?是必須登錄/最好登錄/必須第?次調(diào)?就登錄/不?登錄,并相應(yīng)地指定mode=common/silent/force/不使?requestWithLogin,即可。這樣,我們的登錄模塊可以在不同場景指定不同登錄邏輯,從??持設(shè)計實現(xiàn)更多元更精細更流暢的登錄交互。界?優(yōu)化問題:獲取微信?戶信息時,直接出現(xiàn)系統(tǒng)授權(quán)彈窗有時候是很突兀的;使??定義授權(quán)界?和價值?案進?引導(dǎo),得當(dāng)?shù)脑捒梢杂行?授權(quán)成功率。?且,從10?10號起,?程序?qū)⒉辉?持?動彈窗授權(quán)?戶信息和?動打開權(quán)限?板,這兩種操作必須使?<button>組件由?戶主動觸發(fā)。彼時起,?定義界?將不再是優(yōu)化,?會是必需。這意味著登錄過程必須與頁?dom耦合,之前的純js邏輯不再適?。?案1:登錄浮層在所有頁?放置登錄浮層,頁?需要登錄時則調(diào)起該浮層,經(jīng)由浮層按鈕完成授權(quán)及后續(xù)流程。實現(xiàn)浮層引?各個頁?都需要存在登錄浮層??梢詫⒏鞣N頁?公共dom元素,包括登錄浮層、?絡(luò)異常界?、返回?頁快捷導(dǎo)航、公眾號關(guān)注組件等統(tǒng)?抽離成?個?公共組件,編寫eslint規(guī)則要求所有頁?統(tǒng)?引?,以此實現(xiàn)&保證登錄時浮層存在。浮層?縫時序授權(quán)浮層AuthModal.wpy:<template><viewclass="modal"wx:if="{{show}}"><buttonopen-type="getUserInfo"bindgetuserinfo="onGetUserInfo">登錄</button></view></template><script>importwepyfrom'wepy';exportdefaultclassextendsponent{data={show:false,listener:null,//結(jié)果監(jiān)聽}computed={}methods={onGetUserInfo(ev){//?戶點擊了授權(quán)按鈕this.listener&&this.listener({//回調(diào)授權(quán)結(jié)果succeeded:ev.detail.errMsg.includes('ok'),data:ev.detail,});this.show=false;//關(guān)閉授權(quán)浮層this.$apply();}}//打開授權(quán)浮層open(){returnnewPromise((resolve,reject)=>{this.listener=resolve;//設(shè)置監(jiān)聽this.show=true;//打開浮層this.$apply();//?戶操作結(jié)束后會觸發(fā)監(jiān)聽回調(diào)'resolve',使當(dāng)前Promiseresolve,從??動繼續(xù)執(zhí)?后續(xù)登錄步驟});}onUnload(){//頁?卸載,?戶未點擊按鈕直接返回在此處理this.listener&&this.listener({//授權(quán)失敗回調(diào)succeeded:false,data:null,});}}</script>登錄模塊login.js:_loginSteps={asyncrequestUserInfo(){letpage=getCurrentWepyPage();//獲取當(dāng)前頁?實例letuserInfoRes=awaitpage.$invoke('AuthModal','open');//打開授權(quán)浮層,并監(jiān)聽其操作結(jié)果//正常進?后續(xù)處理if(userInfoRes.succeeded)//授權(quán)成功后續(xù)處理...else//授權(quán)失敗后續(xù)處理...}}如以上代碼所?,雖然?定義浮層需要展?按鈕、等待?戶點擊、處理點擊、考慮?戶不點擊直接返回,交互流程相對復(fù)雜,但依然可以利?Promise使交互細節(jié)對外透明。打開浮層時返回?個Promise,在各個交互出?對Promise進?resolve,則使?時只需將其作為?個普通的異步過程對待。這樣,就可以實現(xiàn)?縫接??定義浮層授權(quán)。?案2:獨?登錄頁需要授權(quán)?戶信息時,跳轉(zhuǎn)??個專門的登錄頁?,頁?中展?引導(dǎo)內(nèi)容和授權(quán)<button>,?戶操作完畢后再?動返回先前頁?。實現(xiàn)元素引?登錄所需dom元素只在登錄頁引?即可。頁??縫時序由于?程序的代碼包特性,各頁?可以共享全局變量和全局函數(shù);并且后?頁?打開時,前?頁?依然駐留在內(nèi)存中,前?頁?遺留的異步任務(wù)也依然會繼續(xù)執(zhí)?。因?,可以在前?頁?設(shè)置監(jiān)聽,在登錄頁進?回調(diào):授權(quán)全局數(shù)據(jù)模塊userAuthHub.js:exportdefault{_listeners:[],subscribe(listener){//前?頁?設(shè)置監(jiān)聽this._listeners.push(listener);},notify(res){//登錄頁進?結(jié)果回調(diào)this._listeners.forEach(listener=>listener(res));this._listeners=[];},}登錄模塊login.js:importuserAuthHubfrom'../lib/userAuthHub';_loginSteps={asyncrequestUserInfo(){letuserInfoRes=awaitnewPromise((resolve,reject)=>{userAuthHub.subscribe(resolve);//監(jiān)聽授權(quán)結(jié)果wx.navigateTo({url:'/pages/login/login'});//打開登錄頁//登錄頁操作結(jié)束后會觸發(fā)監(jiān)聽回調(diào)'resolve',使當(dāng)前Promiseresolve,從??動繼續(xù)執(zhí)?后續(xù)登錄步驟});//正常進?后續(xù)處理if(userInfoRes.succeeded)//授權(quán)成功后續(xù)處理...else//授權(quán)失敗后續(xù)處理...}}登錄頁login.wpy:<template><buttonopen-type="getUserInfo"bindgetuserinfo="onGetUserInfo">登錄</button></template><script>importwepyfrom'wepy'importuserAuthHubfrom'../../lib/userAuthHub';exportdefaultclassextendswepy.page{data={userInfoRes:{//記錄授權(quán)信息succeeded:false,data:null,}}methods={onGetUserInfo(ev){//?戶點擊了授權(quán)按鈕this.userInfoRes={//記錄結(jié)果succeeded:ev.detail.errMsg.includes('ok'),data:ev.detail,};wx.navigateBack();//返回原先頁?}}onUnload(){//頁?卸載,?戶未點擊按鈕直接返回和點擊按鈕授權(quán)后頁??動返回兩種場景在此處統(tǒng)?處理userAuthHub.notify(this.userInfoRes);//回調(diào)授權(quán)結(jié)果}}</script>如以上代碼所?,雖然授權(quán)過程需要進?跨頁?交互,但利?Promise和?程序代碼包特性,可以在前?頁?設(shè)置監(jiān)聽,登錄頁?進?回調(diào)。登錄頁?交互結(jié)束后,前?頁?會?動繼續(xù)執(zhí)?登錄流程,調(diào)???需進?返回刷新等額外處理,數(shù)據(jù)接?也會繼續(xù)調(diào)?,?戶?需再次操作。這樣,就可以實現(xiàn)?縫接?跨頁?授權(quán)交互。兩種?案都可以實現(xiàn)?定義授權(quán)界?。內(nèi)嵌浮層會增加?定維護成本和少量資源開銷,但可以直接在當(dāng)前頁?完成登錄交互,頁??定義空間也相對更?;獨?登錄頁會來回跳轉(zhuǎn)犧牲?定的交互體驗,但可以把登錄所需dom元素集中在登錄頁,減少維護成本和頁?侵?。?者各有優(yōu)劣,可以按需采?或混合使?。這樣,我們的登錄模塊可以使??定義授權(quán)界?,從??持設(shè)計實現(xiàn)更雅觀更精致的授權(quán)引導(dǎo)。復(fù)?優(yōu)化多?程序間復(fù)?&定制問題:開發(fā)?可能同時維護著多個?程序,這些?程序使?著相同的后端接?和后端?戶體系,?有著各?的?程序標(biāo)識和使?訴求。???,希望登錄模塊可以統(tǒng)?維護,不需要每個?程序各?開發(fā);另???,?希望各?程序可以進?差異化定制,包括?程序前端標(biāo)識不?致等剛性差異,和授權(quán)提??案、埋點、授權(quán)交互等個性差異。?案&實現(xiàn):統(tǒng)?流程+個性化配置公共&默認流程由登錄模塊統(tǒng)?維護,各?程序直接復(fù)?;差異流程?持各?程序以配置的形式?定義擴展&覆蓋。e.g.:classLogin{static_config={//可配置項/***剛需:?程序編號,?于區(qū)分不同的?程序,由后端分配*/source:'',/***個性化:?定義?戶授權(quán)交互*@return{Promise<Object>}格式同wx.getUserInfo,或返回null使?默認授權(quán)邏輯*/userAuthHandler:null,//}static_loginSteps={//靜默登錄async_silentLogin({wxLoginRes}){letsilentRes=awaitLogin.request({url:'xxx/mpSilenceLogin',data:{code:wxLoginRes.code,source:Login._config.source,//?程序需要配置??編號,后端根據(jù)編號找到正確的解碼密鑰和id映射表,進?靜默登錄}});//...},//獲取微信?戶信息asyncrequestUserInfo(){//?程序可以配置?定義授權(quán)交互,如:將授權(quán)交互改為?定義浮層/?定義登錄頁/...letuserInfoRes=Login._config.userAuthHandler&&awaitLogin._config.userAuthHandler();if(!userInfoRes)//若未配置?定義交互,亦提供默認授權(quán)交互userInfoRes=...;//}}}配置檢查引?配置過程會存在?個潛在風(fēng)險:觸發(fā)登錄時,?程序尚未完成登錄模塊配置。理論上,只要全局都使?同?個登錄實例并在app.js頂部進?配置,應(yīng)該就沒有這樣的時序風(fēng)險。但復(fù)??是不會?覺的,不?定會使?同?個實例,配置過程也不?定會被放在頂部,甚?有可能被放在某些異步數(shù)據(jù)返回之后。因?登錄模塊只導(dǎo)出唯?實例并加?配置檢查環(huán)節(jié)以保證該邏輯健壯性:/***類修飾器,確保調(diào)?API時已完成?程序信息配置*@paramtargetLogin*/functionrequireConfig(target){for(letpropofObject.getOwnPropertyNames(target)){if(['arguments','caller','callee','name','length'].includes(prop))//內(nèi)置屬性,不予處理continue;if(typeoftarget[prop]!=="function")//?函數(shù),不予處理continue;if(['config','install','checkConfig'].includes(prop)||prop[0]==='_')//配置/安裝/檢查函數(shù)、私有函數(shù),不予處理continue;target[prop]=(function(oriFunc,funcName){//對外接?,增加配置檢查步驟returnfunction(...args){if(!target.checkConfig()){//若未進?項?信息配置,則報錯console.error('[Login]請先執(zhí)?Login.config配置?程序信息,后使?Login相關(guān)功能:',funcName);return;}returnoriFunc.apply(this,args);//否則正常執(zhí)?原函數(shù)}}(target[prop],prop));}}/***登錄模塊命名空間*/@requireConfig//確保調(diào)?API時已完成項?信息配置classLogin{/***登錄*@param{Object}options登錄選項*@param{string}options.mode登錄模式*@return{Promise<Object>}res登錄結(jié)果*/staticasynclogin(options){//...}/***要求登錄態(tài)的數(shù)據(jù)請求*@param{Object}options請求參數(shù),格式同wx.request*@param{Object}options.loginOpts登錄選項,格式同login函數(shù)*@return{Promise}返回結(jié)果,resolve時為數(shù)據(jù)接?返回內(nèi)容,reject時為請求詳情*/staticasyncrequestWithLogin(options){//...}//@requireConfig修飾器會在login、request

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論