getApp()

The getApp() function is used to get an app instance, which is fine in general, but can cause unexpected bugs in a few special situations.

inapp.jsIn theonLaunchUsed in the callback function

// app.js
App({
 onLaunch() {
  console.info(getApp(), '!!!!! '); }});Copy the code

And you’ll notice that undefined is going to be printed at this point, which makes sense, because you’re still in the initialization phase, and your app hasn’t been born yet. If the code is that simple, you can easily spot the problem, and if you call a method in there that accidentally fetches the app instance to get the variable, it’s a surprise.

So if there is no synchronization requirement, the onLaunch function can be called to wrap a layer of setTimout to avoid tramping:

// app.js
App({
 onLaunch() {
  setTimeout(() = > {
   / /... Calling other functions}); }});Copy the code

Assign getApp() to a variable

We create an A.js file:

// a.js
const app = getApp();

export function checkVersion() {
 console.log('checked! ');
 console.info('app', app, '!!!!! ');
}
Copy the code

The files above are normally fine, but once you introduce them in app.js, the surprise happens.

// app.js
import { checkVersion } from 'a';

App({
 onLaunch() {
  console.log('I \' m Fine! ');
 },
 onShow(){ checkVersion(); }});Copy the code

The app variable is undefined. This error may be hard to detect, especially if you use app.js as a generic library.

So~ To avoid this problem, minimize common App instance sharing and instead use getApp() directly in the method to get the instance object. If you want to use global variables, it is better to have a separate JS file to store variables separately, for example:

// globalStore.js

export default {
 userInfo: null.isIos: false.isLaunched: false};Copy the code
// app.js
import store from 'globalStore';

App({
 onLaunch() {
  store.isLaunched = true;
 },
 onShow() {
  const { isLaunched } = getApp().store,
  console.log(isLaunched);
 },
 store,
});

Copy the code

This is compatible with getting global variables via getApp().store as well as importing modules.

In principle, though, I recommend importing global variables by module, since getApp() returns undefined in some cases.

Define variables at the top of the page entry file

It is common to define variables in a page entry file, but it is important to note that the page entry file is executed only once, not independently of each page instance, as in the following code:

// pages/page/index.js
import { getDetailInfo } from 'api';
let ajaxLock = false;

Page({
 onLoad() {
  this.getRemoteData();
 },
 async getRemoteData() {
  if (ajaxLock) {
   return;
  }
  ajaxLock = true;
  try {
   await getDetailInfo();
  } catch(err) {
   / /... Handling errors
  } finally {
   ajaxLock = false; }}});Copy the code

Page logic is simpler, enter the page request remote data, visual also do not have what problem, but more than once at the same time open the page, you’ll find only the first page requests the data, the back of the page without request, because this a few pages are Shared ajaxLock this variable, so the variables at the top of the page statement, it is important to note that the usage scenario.

Assign global variables directly to data in the page entry file

Directly on the code:

// pages/page/index.js
Page({
 data: {
  isIos: getApp().store.isIos,
 },
});

Copy the code
// app.js
App({
 onLaunch() {
  this.getSysInfo();
 },
 getSysInfo() {
  return new Promise((resolve, reject) = > {
   wx.getSystemInfoAsync({
    success: resolve,
    fail: reject,
   });
  }).then((res) = > {
   const { store } = getApp();
   store.isIos = res.platform.toLowerCase() === 'ios';
  });
 },
 store: {
  isIos: false,}});Copy the code

The main logic of the code above is need to know whether the current equipment ios, code on the simulator run seemed very stable, but once on the real machine, downs, because isIos this variable is not synchronize access to state, once the assignment function performs the entrance of the page, then the state of the show is not correct.

Therefore, for some states that are not synchronous assignment, do not directly assign data at initialization. It is better to assign the state in the onLoad callback function.

You don’t know the wx. CreateSelectorQuery () and wx. CreateIntersectionObserver ();

These two functions is relatively common, wx. CreateSelectorQuery is mainly used to query an element, wx. CreateIntersectionObserver on whether need processing elements in the visible area. The problems of these two functions are visually pure and lovely, and I only found them when I realized a special requirement. It is really a matter of hindsight and hindsight.

To duplicate the problem, the page entry function says:

// pages/page/index.js
let index = 0

Page({
 data: {
  tag: 0
 },
 onLoad() {
  if (index++ < 2) {
   wx.navigateTo({
    url: '/pages/page/index'
   });
  }
  this.setData({
   tag: index
  },() = > {
   setTimeout(() = > {
    const { tag } = this.data;
    const query = wx.createSelectorQuery();
    // const query = this.createSelectorQuery();
    query.select(`.c-${ tag }`).boundingClientRect();
    query.exec((res) = > {
     console.log(tag, res);
    });
   }, 2000); }); }});Copy the code
<! -- Template file -->
<view class="c-{{tag}}">demo</view>
Copy the code

I simulated having multiple pages open at the same time, and in the developer tool you will find that the first two pages are null!! I felt like the world was falling apart. So I suspect that after all, wx.CreatesElectorQuery is a global function, so it queries WXML under the current active window. I looked through the official documentation, looked through the fine print with a magnifying glass, and found this. CreateSelectorQuery. Of course wx createIntersectionObserver is also the same problem, I will not making a presentation.

So ~ good for the body, I strongly recommend direct use of enclosing createSelectorQuery and enclosing createIntersectionObserver.

The above is my development in recent years micro channel small program stepped on the god pit, hope you don’t step on ~~