求问,怎么才能先执行app.js,执行完了,才执行page里的js呢
发布于 5 年前 作者 chao61 7939 次浏览 来自 问答

如题,我想在app.js里用接口获取一个参数,用到page里面,显示在页面上,但是每次页面加载完了,app.js才获取到参数,这怎么办呢

10 回复

唔,怎么看上去有些复杂了呢,分两种吧,

  1. 非要在 app.js 里面运行的
//app.js
App({
  onLaunch: function() {
    this.post_entry(res => {
      this.entry_data = res;
      console.log('加载完成')
      this.post_entry_finish(res)
    })

  },

  // 获取数据

  post_entry: function(cb) {
    setTimeout(cb, 2000)

  },

  // 获取数据完成

  // entry_finish 比 post_entry 快,则保存函数
  // post_entry 比 entry_finish 快,则直接运行
  entry_finish: function (cb) {
    if (this.entry_data) {
      cb && cb(this.entry_data)
    else {
      this.post_entry_finish = cb
    }

  },

  // 获取数据完成,在 index.js 再运行部分

  post_entry_finish: function(cb) {
  },
})
 
// index.js
var app = getApp()
Page({

  onLoad: function () {

    // app.js 里的 post_entry 运行完再运行这个

    app.entry_finish(res => {
      console.log('x')
    })
  },
})
  1. 可以放在 index.js 里面运行的
// app.js
App({
  post_entry: function(cb) {
    setTimeout(cb, 2000)
  },
})
 
// index.js
Page({
  onReady: function () {
    app.post_entry(res => {
      console.log('x')
      this.entry_finish(res)
    })
  },
  entry_finish: function(){}
})

贴的图代码还多了,必要代码就是loginSuccessCallback。你只要理解,多种场景下,app.js中异步请求的同时,page.js已经走了onLoad方法,此时使用只有app.js中请求成功后才可能有值的detail做判断,若detail为空,则给app.js注册一个loginSuccessCallback回调,这个回调方法的执行时机,就是app.js中的异步请求完毕,如图所示,仅此而已。

试了下,还是没弄好,心累

先贴代码

app.js

wx.getUserInfo({
          success: res => {
            this.globalData.userInfo = res.userInfo;

           // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回,所以此处加入 callback 以防止这种情况

           if (this.userInfoReadyCallback) {

              this.userInfoReadyCallback(res);
            };
          },
        })

page.js

onLoad: function () {

   // 判断全局的userInfo是否存在

    if (app.globalData.userInfo) {
      this.setData({
        userInfo: app.globalData.userInfo,
      })

    }

   // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回,所以此处加入 callback 以防止这种情况

    else {
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
        })
      }
    }
  },

原理:在app.js中加入一个条件判断,若条件中的callback被赋值存在,则传入wx.getUserInfo的参数res。

在page.js中,判断全局app.globalData.userInfo是否存在,存在则正常赋值。不存在则说明wx.getUserInfo的异步请求晚于page.js的调用,那么就将setData函数赋值给app.js中的callback,callback传入res调用后,page中的userInfo也就被设置好了。

p.s.这个方法来源于官方的示例代码。

我的理解是这样,不知道是不是有帮助,如有错误请指出。

onLaunch: function () {
     
   // 展示本地存储能力
   var logs = wx.getStorageSync('logs') || []
   logs.unshift(Date.now())
   wx.setStorageSync('logs', logs)
   // 登录
   wx.login({
     success: res => {
       console.log(res.code)
       // 发送 res.code 到后台换取 openId, sessionKey, unionId
       if (res.code) {
         //发起网络请求
         wx.request({
           url: this.globalData.url+'/auth/user/authorize/',
           data: {
             code: res.code
           },
           success:(res)=>{
             if(res.data.code == 0){
             console.log(res)
             var data=res.data
             // console.log(data)
             wx.setStorage({
               key:'ticket',
               data:{ticket:data.data.ticket,id:data.data.user_id}
             })
             }
           }
         })
       } else {
         console.log('获取用户登录态失败!' + res.errMsg)
       }
     }
   })

这是app.js部分,获取到ticket值,并且存储起来

*/
onLoad: function () {
  console.log(1111111111111111+"onload")
  var that = this;
 
  wx.getStorage({
    key: 'ticket',
    success: (res) => {
      console.log(res)
      var ticket = res.data.ticket;
      var id=res.data.id
      that.setData({
        ticket:ticket,
        id:id
      })
    },
  })
},

这是index.js中onLoad部分,当我一次进来时拿不到ticket值,手动刷新一下才能拿到

onReady: function () {
   console.log(this.data.ticket)
   var that = this;
   var ticket = this.data.ticket
   console.log(ticket)
   wx.request({
     url: app.globalData.url +"/source/campus/",
     data: { ticket: ticket, pagination: false },
     success: (res) => {
       console.log(res)
       var item=res.data.data
       if(res.data.code == 0){
       for(var i =0;i<item.length;i++){
         item[i].count=i
         item[i].checked=false
       }
       that.setData({
           item:item
       })
       }
     }
   })
   console.log(ticket)
   console.log(this.data.id)
   wx.request({
     url: app.globalData.url +"/auth/user/info/"+this.data.id+"/?ticket="+this.data.ticket,
     data:{ticket:ticket},
     success:(res)=>{
       if (res.data.code == 0) {
       console.log(res.data.data)
       var temp=res.data.data.wcampus
       var item=that.data.item
       for(var i=0;i<temp.length;i++){
         for(var j=0;j<item.length;j++){
           if(temp[i]==item[j].id){
             item[j].checked=true
             console.log(item[j].checked)
             if(res.data.data.email!=""){
             that.setData({
               username:res.data.data.name,
               userEmail:res.data.data.email,
               userWechat:res.data.data.wechat,
               userSchool:res.data.data.cschool,
               item:item,
               state:"1"
             })
             }
           }
         }
       }
       }
     }
   })
 },

这是index中onReady部分。要通过上面获取的ticket值,在向后台请求数据时发送过去,才能拿到对应的数据。

现在问题就是第一次拿不到ticket值,获取不到数据,各位大佬帮忙看下,怎么样解决啊

大哥,能把代码多贴一点么

app.js

page.js

当然,callback可以传参

看上图中的loginSuccessCallback

请问下,为什么在第一次登陆的时候,不能拿到数据,在刷新后就可以拿到数据库的数据了,这是为什么?

把相关的渲染过程写成页面里一个单独的函数,在app执行成功之后通过getCurrentPage后直接调用page里的这个函数

回到顶部