zoukankan      html  css  js  c++  java
  • JS利用async、await处理少见的登录业务逻辑

      在用uniapp开发一个项目时,有这样一个需求:用户首次登录后,uniapp自动保存用户名密码,之后不管是再次打开项目(打开项目时登录状态已失效)还是 请求接口(接口返回登录失效)时,都会先自动默认的登录,然后再进行之后的操作。

      比如页面需要调用功能接口1、2,但是必须是登录状态。如下图所示:

      

      根据图中的逻辑流程可以断定共有 登录接口、功能接口1、功能接口2 三个request请求,我们抛开要跳转登录页的情况下,那么打开页面会有两种需要特殊处理的情况:

      1.没有登录状态,程序默认调用已存的用户名和密码去调用登录接口,接口登录成功后再继续调用功能接口1和2。

      2.页面已存在登录状态(比如vuex判断是否登录),但是调用接口1或者2时返回需要登录的状态(可能页面停留时间过久,服务器保存的登录状态已失效),这时需要跳到第一种情况去执行。

      

       根据上述的两种情况,我们常见的解决办法就是

     1 //页面执行
     2 if(!loginStatus){//页面判断是否登录
     3     login();
     4 }else{
     5      server();   
     6 }
     7 //假如server中的catch为接口返回登录失效,需要重新登录
     8 function server(){
     9     
    10         server1Promise().then(()=>{
    11         }).catch(()=>{
    12                login();
    13         })  
    14         server2Promise().then(()=>{
    15         }).catch(()=>{
    16                login();
    17         })  
    18 }
    19 function login(){
    20      loginPromise().then(()=>{
    21         server();      
    22     })
    23 }
    View Code

      这样会有很多问题,比如  无法分开调用接口1、接口2(有时候页面逻辑会需要分开调用); 同时调用接口1和2,都返回需要登录状态时,会重复去请求登录接口,进而重复请求接口1和2。

      那么就需要另一种解决方法能同时解决这个问题! 

      

    ///  request.js
    const request = (data,url) = >{
        return new Promise((s,f)=>{
            uni.request({//也可以是其他的接口请求
                 complete(r){
                     if(r.statusCode == 200) 
                         s(r);
                     else
                         f(r);
                 },
                 url:url,data:data
             })
        })
    }
    
    let isLogin =false;//是否正在登录
    let loginStatus = async function () { return true}();//登录结果,默认可以登录
    const _req = async (_d,_u)=>{
        return new Promise((s,f)=>{
        let _let_go =  await loginStatus.catch(()=>{return false;});
        if(_let_go){
            request(_d,_u).then((r)=>{
                s(r)//接口返回正常
            }).catch(()=>{
                //假使catch是调用业务接口返回要登录
                autoLogin();//自动登录
                let _let_go_n = await loginStatus.catch(()=>{return false;});
                if(_let_go_n){
                    request(_d,_u).then((r)=>{ s(r)}).catch(()=>{ f({status:0,msg:'请登录'}) }) //再次请求,如果还是失败就不再继续
                }else{ f({status:0,msg:'请登录'})}
            })
        }else{
            //已经调用了登录接口,还是失败,那么跳转到登录页
            f({status:0,msg:'请登录'})
        }
        });
    }
    
    //自动登录
    const autoLogin = ()=>{
        if(isLogin ){return}
        var _f = ()=>{ 
                    isLogin =true;
            return new Promise((s, f) => {
                var userinfo= uni.getStorageSync('userinfo');//读取保存的用户名密码
                            if(userinfo){
                                request(userinfo,'login').then(()=>{isLogin =false;s(true)}).catch(()=>{isLogin =false;s(false)});
                            }else{isLogin =false;s(false)}
    
                    })
         }
         loginStatus = _f();  
    }

    //业务接口
    const server1 = (_d)=>{
    return _req(_d,'server1')
    }
    const server2 = (_d)=>{
    return _req(_d,'server2')
    }

    //登录接口,登录接口要和autoLogin分开,在login成功后要保存用户名和密码
    const login = (_d)=>{ ... }

    export default {server1,server2,login }


    /// page.vue
    import request from 'request.js'
    ...
    业务逻辑
    ...
    request.server1().then()
    ...
    业务逻辑
    ...
    request.server2().then()
  • 相关阅读:
    Swift 懒加载
    Swift 模型属性
    Swift 循环引用
    Two Sum
    Best Time to Buy and Sell Stock II
    Best Time to Buy and Sell Stock I
    Pascal's Triangle II
    杨辉三角(数组)
    Merge Sorted Array 合并数组
    Plus One
  • 原文地址:https://www.cnblogs.com/tohert/p/11984209.html
Copyright © 2011-2022 走看看