一、问题描述

最近碰到一个奇怪的生产问题:
正常情况下、前端页面会请求一次后台、然后后台返回信息("处理成功""处理失败")、前端展示;
后台用aop+redis写了一个防止重复调用的方法,如果5s内同一个用户重复调用同一个接口,就返回"请勿重复调用",前端就会展示这个。

但是,某几个页面,前端总是会重复调用后端2次,导致用户只能看到"请勿重复调用",无法确认本次操作是成功还是失败,严重影响了用户的正常使用。(虽然是处理成功,但是显示不出来…)

一开始还怀疑是不是后端的问题,排查了半天,终于锁定了,是前端的问题,vue项目中的created()方法被调用了2次

继续排查,发现从正常页面跳转到这个问题页面时,确实只跳转了1次,按理说created()方法应该也只触发1次的,但是就是不知道为什么触发了2次。

二、排查过程

1.从头开始排查前端项目,vue项目首先会加载main.js,发现这个文件里有:

import Vcon from './assets/js/vcon'new Vcon({env: ENV
}, () => {new Vue({router,render: h => h(App)}).$mount('#app')
})

发现这个文件里,并不是普通的使用new Vue()创建的页面,而是外面有封装了一个new Vcon()方法,并传了2个参数,其中第一个参数是{ env: ENV },第二个参数是 () => { new Vue({ router, render: h => h(App) }).$mount('#app') }

2.继续,查看./assets/js/vcon.js文件,发现这个文件里有类似这样的:

class Vcon {constructor (opt, callBack) {this.env = opt.env || '' // 记录代码环境this.callBack = callBack // 记录回调函数// 如果是生产环境if (this.env !== 'test') {this.prodInit()typeof this.callBack === 'function' && this.callBack()return}// 如果是测试环境if (this.env === 'test') {this.testInit()return}}testInit () {import('vconsole').then(({ default: VConsole }) => {new VConsole()console.log('测试vconsole加载完成')typeof this.callBack === 'function' && this.callBack()})}prodInit () {let _that = thiswindow.ISALES.callApp('getUserInfoByNative', {callback: function (userInfo) {if (userInfo.code === '0') {_that.betterStaffNUmber = userInfo.msg.staffNumber_that.betterHandler(userInfo)return}alert('获取sdk出错,请稍后再试')}})}betterHandler (userInfo) {if (userInfo.msg.userCode == 'admin') {import('vconsole').then(({ default: VConsole }) => {new VConsole()console.log(`admin的vconsole加载完成`)typeof this.callBack === 'function' && this.callBack()})return}else{this.callBack()}}}

其中,当上一步执行new Vcon()时,实际执行的就是这里的constructor ()方法;
如果是测试环境,那就执行testInit ()方法,这个还是比较明显的,用来展示vconsole(测试环境一直正常,没有复测出来问题);
如果是生产环境,那就执行prodInit()方法,然后执行typeof this.callBack === 'function' && this.callBack()方法(这里感觉有些问题,先继续看);

prodInit()方法里,会执行window.ISALES.callApp方法,这个是个sdk方法(这个前端项目是vue项目,可以打包后把静态页面部署在服务器上;sdk方法是app和ios里的方法,前端只能这样才能调用到、待sdk方法处理完后会触发callback方法);

sdk方法中,会执行betterHandler()方法,意思是,如果当前app/ios的登录人是admin,那就显示vconsole,否则就不显示。

3.根据生产created()方法被调用2次、而测试正常的现象,排查到问题方法位置:

    // 如果是生产环境if (this.env !== 'test') {this.prodInit()typeof this.callBack === 'function' && this.callBack()return}

因为prodInit()方法的逻辑中,正常情况下,已经调用过一次typeof this.callBack === 'function' && this.callBack()了,然而执行完prodInit()方法后,又会调用一次typeof this.callBack === 'function' && this.callBack(),所以才导致created()方法被重复调用了2次。

4.正确代码如下:

    // 如果是生产环境if (this.env !== 'test') {this.prodInit()//这里导致了重复created()//typeof this.callBack === 'function' && this.callBack()return}

修改后,发布生产,终于恢复了正常。

三、备注

1.vue项目中,有时会自动优化代码格式,导致if后面没有大括号、只有1句,满足条件就执行、不满足就不执行,需要注意。

2.有时,if没有else,而是if中结尾有个return,此时也类似else,但是容易忽略,需要注意。(这个也是自动优化格式的?还是故意写的难懂了?)

3.typeof this.callBack === 'function' && this.callBack(),这个的意思是,如果this.callBackfunction类型的,那就会执行后面的this.callBack()方法,然后继续下一步;如果不是function类型的,那就不执行后面的方法,直接继续下一步。(又一个不好理解的高级写法,用if不好吗?)

4.正常情况下,vue页面的created()方法会在页面初始化的时候执行1次;但是如果代码有问题,就会导致created()方法会在页面初始化的时候执行2次或多次(如本文),这个坑需要注意。

vue项目created()被调用多次的坑相关推荐

  1. vue之猫眼json数据的获取直接用于自己的vue项目中,swiper轮播插件的坑

    vue之猫眼json数据的获取直接用于自己的vue项目中 遇到问题总结: 加载不出猫眼数据,无法调用,数据被限制 猫眼电影图片的拼接及删除问题 swiper的迷幻坑** 首先来说一下第一问题 加载不出 ...

  2. 在Vue项目中离线调用阿里巴巴Iconfont

    文章目录 问题概述 挑选自己喜欢的图标 下载代码 使用图标 问题概述 最近在学习Vue前端开发中,发现Element-UI中的Icon不够用,就从阿里巴巴矢量图标库下载了一些到项目中使用,这里介绍离线 ...

  3. Vue项目如何过滤全部console.log输出(浅水魚)

    Vue项目如何过滤全部console.log输出 在App.vue的created中调用一个consoleCancle方法 然后在methods中创建一个consoleCancle方法,让consol ...

  4. Vue进阶(十六):Vue 项目启动原理详解

    文章目录 一.前言 二.文件介绍 三.拓展阅读 一.前言 vue项目启动后调用顺序: index.html → main.js → app.vue → index.js → components/组件 ...

  5. Vue项目中 sass安装

    1. sass-loader依赖于node-sass,所以要安装node-sass cnpm install node-sass --save-dev //安装node-sass cnpm insta ...

  6. UNI-APP/VUE 项目集成 微信SDK /微信开放标签 教程和避坑指南

    UNI-APP/VUE 项目集成微信SDK教程和避坑指南 文章同步发布于

  7. 如何在vue项目中调用微信扫一扫

    今天公司有一个用vue写的微信公众号的项目,里面有个1扫一扫,刚开始我看了都蒙蔽了.没接触过,一头雾水,然后在网上查了下,官网需要引入一个js文件`链接如下微信公众号官方文档 但是vue项目所以就在网 ...

  8. vue项目中调用高德地图vue-amap 插件 的AMap.PlaceSearch简用

    vue项目调用高德地图vue-amap 插件 的AMap.PlaceSearch简用 结合 elementui 的 el-input 直接下拉选取地点 不展示地图 1.下载 npm install v ...

  9. vue项目:(全局变量设置与调用)API接口封装 - 代码篇

    vue项目,如何将"API接口" 封装为"全局变量" ? 1. API全局配置文件[global.vue文件] <template><div& ...

最新文章

  1. 激光slam-- .pgm格式地图分析及修改方法
  2. android tomtom gps location,TomTom智能地图修正 规避不能走的路
  3. VC6开发视频监控ActiveX控件总结
  4. java 模块化osgi_OSGi简介–模块化Java
  5. 优客365导航系统美化UI版源码-带交易功能
  6. typecho博客主题 “Freedom-冷文”
  7. php 获取mysql大小限制_php计算整个mysql数据库大小的方法
  8. linux c语言变量地址类型,C语言基础知识:访问内存地址的方法
  9. 蔚来2018年平均每天亏掉2641万,车辆交付预期环比腰斩
  10. 常见系统中文字体的英文名
  11. 消息系统——极光推送http://docs.jiguang.cn/
  12. 《墨菲定律》读书笔记(上)
  13. The Elder(树形dp 斜率优化)
  14. 在线流程图和思维导图开发技术详解(六)
  15. 灾难恢复_有效的灾难恢复计划的10个技巧
  16. 个人计算机cpu型号,终于知道如何看懂一个电脑CPU型号了!
  17. 三网融合触发MeeGo风暴
  18. 计算机基础实验指导第3版答案,计算机基础实验指导(第3版)
  19. 计算机应用基础.ppt,计算机应用基础.ppt
  20. 疫情之下的企业该如何生存?

热门文章

  1. 机器学习:使用scikit-learn的线性回归预测Google股票
  2. vue-seamless-scroll 列表自动滚动
  3. JetBrains .idea project directory (详细利用教程)
  4. Sicily 1048. Inverso
  5. Apache 服务器 SSL 证书到期-续期处理步骤
  6. 【ISP】Sharpen(2)
  7. 【分享】SDLPAL 仙剑奇侠传开源项目编译
  8. 【unittest学习】unittest框架主要功能
  9. sqlserver ssis
  10. 使用rrdtool统计网站PV和IP