[DingTalk applet] Solve the problem of app.js onLaunch asynchronous request and enter page onLoad before the request is executed

problem scenario

In the process of writing small program projects recently, every step is really a "giant pit". This time, in the process of realizing the login-free process, we need to get the returned data in app.jstoken first , and tokensend a request on the home page to obtain the data that needs to be displayed on the home page.

OK, this is the order in which we want the applets to be executed, but the execution order of the applets is to execute app.js onLaunch first , dd.getAuthCodeobtain the authorization code without login, access-tokenthen codeobtain it through and userid, and useridobtain it token . The whole process is asynchronous, so when we need to carry the request data in page onloadtoken , the asynchronous request in onLaunchtoken has not yet been obtained , but at this time page onload has already displayed it before the data has been obtained.

Let me show you the output sequence of the console:

insert image description here
It can be seen that the data output of the home page is executed first , and then the data requested in the app has nothing to do with the home page, because the home page has already been executed.

resolution process

Some articles say to customize a function on app.js (the tokenCallBack method in the downlink code). When home.js is not obtained token, call this method in the apptoken to get it and then execute the following code.

home.js code:

const app = getApp();
Page({
    
    
  data:{
    
    
    // 存储首页所有的展示信息
    allList:[],
  },
  async onLoad() {
    
    
    // 从本地获取 token 
    let token = dd.getStorageSync({
    
     key: 'token' }).data;
    // 判断本地是否有 token,如果没有,就在本地存一个 token,如果有 token,就直接调用接口
    if (token == null) {
    
    
      // 在顶级对象里面添加一个 tokenCallBack 方法
      app.tokenCallBack = async (token) => {
    
    
        if (token) {
    
    
          dd.setStorageSync({
    
    
            key: 'token',
            data: token
          })
          // 发起请求,请求接口
          let result = await app.httpsReq('GET', '/**/**')
          if(result.status === 200){
    
    
            this.setData({
    
    
              allList : result.data.data
            })
          }
        }
      }
    } else {
    
    
      // 如果有 token ,就直接发起请求
      let result = await app.httpsReq('GET', ''/**/**'')
    }
  },
});

app.js code:

APP({
    
    
  onLaunch(options) {
    
    
    // 调用 istoken方法,实现免登陆
    this.isToken();
  },
  isToken(){
    
    
    // 将顶级对象的 this 存储到 this2 中
    const this2 = this
    // 获取免登授权码(方法 API 文档提供)
    dd.getAuthCode({
    
    
      success:function(res){
    
    
        // 存储 authorCode 
        this.authCode = res.authCode
        // 将方法 getAuthCode 的 this 存储到 _this 中
        let _this = this
        // 根据 appkey 和 appsecret 获取 access-token
        dd.httpRequest({
    
    
          url:'https://oapi.dingtalk.com/gettoken?appkey=**&appsecret=**',
          method:'GET',
          success: (res) => {
    
    
            _this.access_token = res.data.access_token
            // 根据 access-token 和 code 获取 userid 
            dd.httpRequest({
    
    
              url:'https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token=' + _this.access_token + '&code=' + _this.authCode,
              method:'POST',
              success: async(res) =>{
    
    
                _this.userid = res.data.result.userid
                // 根据 userid 获取 token
                let result = await this2.httpsReq('POST','/**/**',{
    
    'userid':_this.userid})
                // tokenCallBack 方法用于在本地存储 token
                if(this2.tokenCallBack){
    
    
                  this2.tokenCallBack(result.data.data.token)
                }
              }
            })
          }
        })
      },
      fail:function(err){
    
    
        console.log(err);
      }
    })
  },
})

Unfortunately, this problem has not yet been resolved. Many writing methods were also tested during the period, but if the asynchronous problem is not solved, the result will be the same.

final code

In the end, my partner accidentally clicked into an article. The writing above is the same, except that the code written in onLoad in home.js is mentioned in a method (in the next line ), and then called in onLoad This method solves this problem. . . Honestly, sloppy, but it works...getdata()

home.js code:

const app = getApp();
Page({
    
    
  data: {
    
    
    // 存储首页所有的展示信息
    allList: [],
  },
  onLoad() {
    
    
    // 获取首页数据
    this.getdata()
  },
  // 用来发起请求获取首页数据的方法
  async getdata() {
    
    
    // 从本地获取 token 
    let token = dd.getStorageSync({
    
     key: 'token' }).data;
    // 判断本地是否有 token,如果没有,就在本地存一个 token,如果有 token,就直接调用接口
    if (token == null) {
    
    
      // 在顶级对象里面添加一个 tokenCallBack 方法
      app.tokenCallBack = async (token) => {
    
    
        if (token) {
    
    
          // 将 token 存到本地
          dd.setStorageSync({
    
    
            key: 'token',
            data: token
          })
          // 发起请求,请求接口
          let result = await app.httpsReq('GET', '/**/**')
          if (result.status === 200) {
    
    
            // 通过 setData 修改数据
            this.setData({
    
    
              allList: result.data.data
            })
          }
        }
      }
    }
    else {
    
    
      // 如果有 token ,就直接发起请求
      let result = await app.httpsReq('GET', '/**/**')
      if (result.status === 200) {
    
    
        // 通过 setData 修改数据
        this.setData({
    
    
          allList: result.data.data
        })
      }
    }
  },
});

app.js code:

APP({
    
    
  onLaunch(options) {
    
    
    // 调用 istoken方法,实现免登陆
    this.isToken();
  },
  isToken(){
    
    
    // 将顶级对象的 this 存储到 this2 中
    const this2 = this
    // 获取免登授权码(方法 API 文档提供)
    dd.getAuthCode({
    
    
      success:function(res){
    
    
        // 存储 authorCode 
        this.authCode = res.authCode
        // 将方法 getAuthCode 的 this 存储到 _this 中
        let _this = this
        // 根据 appkey 和 appsecret 获取 access-token
        dd.httpRequest({
    
    
          url:'https://oapi.dingtalk.com/gettoken?appkey=**&appsecret=**',
          method:'GET',
          success: (res) => {
    
    
            _this.access_token = res.data.access_token
            // 根据 access-token 和 code 获取 userid 
            dd.httpRequest({
    
    
              url:'https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token=' + _this.access_token + '&code=' + _this.authCode,
              method:'POST',
              success: async(res) =>{
    
    
                _this.userid = res.data.result.userid
                // 根据 userid 获取 token
                let result = await this2.httpsReq('POST','/**/**',{
    
    'userid':_this.userid})
                // tokenCallBack 方法用于在本地存储 token
                if(this2.tokenCallBack){
    
    
                  this2.tokenCallBack(result.data.data.token)
                }
              }
            })
          }
        })
      },
      fail:function(err){
    
    
        console.log(err);
      }
    })
  },
})

My partner and I thought about many kinds of guesses to explain why this problem can be solved by mentioning these codes in a method, but I feel that there is no exact knowledge support.

I think a more reasonable explanation may be that when the applet is started for the first time or the page is loaded for the first time, initialization will be performed first. After the datadata in the initialization and some custom methods are completed, onLaunchthe or onLoadcallback function will be triggered. At this time, the data and methods have been completed. After the rendering is completed, it is ok to use it directly. However, the official document does not explain in detail what preparations are made during the life cycle of the applet page, so our guess above may be wrong, but we really can't think of a better explanation.

If you have other or better solutions, please let me know!
If wrong, please correct me!

Guess you like

Origin blog.csdn.net/aDiaoYa_/article/details/130011646