前端框架:点滴记录

533 阅读4分钟

1. 新老版本对比

No老版本新版本
1.NodeJs8.9.1NodeJs16.13.0
2.Mysql2.15.1Mysql2.18.1

2. 技术变迁

迁移过程中:老版本的代码,在新版本环境中面临以下窘境。

  • Callback地狱模式早已不适应新时代发展
  • 部分代码完全不能执行。
  • 编码方式已发生改变。

3. 在有限资源及有限时间,如何快速升级?

3.1 编码方式:commonJS和Module(ES6方式)

  • commonJS:接近老版本方式,风险较低
  • Module:需要框架整体变化,风险较大

3.2 callback地狱模式改进

有两种选择

  • Promise模式:解套callback,有限修改
  • await/async:全盘考虑,重新构建

3.3 下层如果是callback的情况下,怎么修改?

老版本:---test exports.aaaa=function(callback){ ... callback.Success(true); ... callback.Failure(err); } test.aaaa({ Success:testA, Failure:testB }); 新版本:---test exports.aaaa=function(){ return new Promise(function(resolve,reject){ ... resolve(true); ... reject(err); }); } test.aaa().then(v=>{}).catch(reason=>{});

3.4 下层如果是多个的情况下,该如何是好?

新版本:test Promise.all([aaa,bbb]) .then(r=>{}) .catch(reason=>{ });

4. 如果考虑bean进行属性复制,nodejs怎么做呢?

Object.assign(to,from);

5. 找寻几个昼夜,执行突然中断,原因一定要小心?

  • A. 不该resolve()的地方,手欠多写了一句
  • B. Promise执行方式,通常的写循环的语句可能都失灵了:考虑用递归
  • C. 尤其NodeJS写Batch一定要想好启动及结束条件是怎样的。

循环形式如下:

collections.forEach(function(collection){
    // 内部逻辑处理(这部分验证过基本是并发执行)
});

如想顺序执行,可修改成如下两种形式:

5.1 顺序执行,async方式

async.eachSeries(
    collections,
    function(collection,iteratorCallback){
        // 内部逻辑处理(这部分验证过基本是顺序执行)
    },
    function(error){
        // 都处理完的逻辑
    })

5.2 顺序执行,递归方式

let loopList = (index) => {
    if(index > 100){
        return;
    }else{
        loopFunction(index);
        
        index=index+1;
        loopList(index);
    }
}
loopList(0);

6. 如何像java那样,把相同逻辑共通化,不同逻辑提取出来?

函数作为参数,传递下去,写起来虽然怪怪的;至少可以少写轮子,如下:

定义的地方:

exports.doSomething = function(a,b,doFunction){
    const buss = {busses:'doSomething'};
    logger.info("process start ",buss);
    return new Promise(function (resolve, reject){
        doFunction(a,b)
           .then(res=>{
               resolve();
           })
           .catch(reason=>{
               reject(reason);
           });
    }).finally(()=>{
        logger.info("process end ",logBuss);
    });
}

调用的地方:

const some = require('/moduleA');
function doFun1(a,b){
    const buss = {busses:'doFun1'};
    logger.info("process start ",buss);
    return new Promise(function (resolve, reject){
        try{
            resolve(a+b);
        }catch(err){
            reject(err);
        }
    }).finally(()=>{
        logger.info("process end ",logBuss);
    });
}
some.doSomething(1,2,doFun1);

7. 日志部分

日志输出方向:控制台,文件,AWS CLOUDWATCH

查看详细代码
const winston = require('winston');
require('winston-daily-rotate-file');

const consoleTransport = new winston.transports.Console({
    level: 'debug',
    silent: false
});
const AWS = require('aws-sdk');
const CloudWatchTransport  = require('winston-aws-cloudwatch');

AWS.config.update({
    region: process.env.LOG_RIGION_NAME,
});
const fileTransport = new winston.transports.DailyRotateFile({
    level: 'info',
    silent: false,
    handleExceptions: true,
    filename: process.env.LOG_INFO_FILE_NAME,
    datePattern: 'MM-DD'
});
const errorTransport = new winston.transports.DailyRotateFile({
    level: 'error',
    name: 'error-file',
    handleExceptions: true,
    filename: process.env.LOG_ERROR_FILE_NAME,
    datePattern: 'MM-DD'
});
const cloudWatchTransport = new CloudWatchTransport ({
    logGroupName: process.env.LOG_GROUP_NAME,//REQUIRED
    logStreamName: process.env.LOG_STREAM_NAME,//REQUIRED
    createLogGroup: true,
    createLogStream: true,
    submissionInterval: 2000,
    submissionRetryCount: 1,
    batchSize: 20,
    awsConfig: {
        accessKeyId: '',
        secretAccessKey: '',
        region: process.env.LOG_RIGION_NAME
    },
    formatLog:item => {

        let meta = item._meta;
        let message = item._message;

        let level = 'item';
        if(item.level.includes('debug')){
            level = 'debug';
        }
        if(item.level.includes('warn')){
            level = 'warn';
        }
        if(item.level.includes('error')){
            level = 'error';
        }
        if(meta.metadata !=undefined && meta.metadata != null){
            let out = ``;
            Object.keys(meta.metadata).forEach(function (key){
                out += `[` + meta.metadata[key] + `]`;
            });
            return `[${meta.label}]` + out + `${level}:${message}`;
        }else{
            return `[${meta.label}]${level}:${message}`;
        }
    }
});
let logger = winston.createLogger({
        level: 'info',
        exitOnError: false,
        format: winston.format.combine(
            winston.format.label({ label: 'test' }),
            winston.format.timestamp({
                format: 'YYYY-MM-DD HH:mm:ss'
            }),
            winston.format.colorize(),
            winston.format.splat(),
            winston.format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }),
            winston.format.printf((item) => {
                let out = ``;
                if (Object.keys(item.metadata).length > 0) {
                    Object.keys(item.metadata).forEach(function (key){
                        out += `[` + item.metadata[key] + `]`;
                    });
                    return `${item.timestamp}[${item.label}]` + out + `${item.level}:${item.message}`;
                } else {
                    return `${item.timestamp}[${item.label}]${item.level}:${item.message}`;
                }
            }),
        ),
        transports: [consoleTransport,fileTransport,errorTransport,cloudWatchTransport]
    });

module.exports = logger;

8. 数组操作

在操作DB时,为了安全起见通常采用?的方式来作为参数占位符。这个时候,就会有一个问题,如何给参数赋值:

  • 一般做法,往参数数据推送数据,例如:
let arr=[];
arr.push(arr);
  • 遇到多个参数时,有时也会合并数据,例如:
let arr=[1,2];
let val=[3,4,5];
Array.prototype.push.apply(arr,val);

9. 多进程合并执行

nodejs中,使用package.json中scripts片段,很方便。

单功能A,如下:

"scripts": {
"start-A:dev": "node -r dotenv/config ./app A dotenv_config_path=./config/.env.dev ",
}

单功能B,如下:

"scripts": {
"start-B:dev": "node -r dotenv/config ./app B dotenv_config_path=./config/.env.dev ",
}

上面两个功能单独执行,没有任何问题。

9.1 但如果想让功能A和功能B一起执行的话,该如何处理?

针对这种问题,nodejs给出了两种解决方案:

  • 顺序执行,使用 && 来连接,代码如下:
"start:dev": "npm run start-A:dev && npm run start-B:dev",
  • 并发执行,使用 & 来连接,代码如下:
"start:dev": "npm run start-A:dev & npm run start-B:dev",

注意:并发执行时,如果打日志会很混乱。

9.2 如果在连接好的命令前后加些处理,又该如何?

nodejs也给出了解决方案,pre命令---post命令,如下:

"prestart:dev": "npm run commandPre",
"start:dev": "npm run start-A:dev & npm run start-B:dev",
"poststart:dev": "npm run commandPost",

10. vue3 element ui

10.1 el-dialog每启动一次z-index累加

  • Q:导致z-index的值超过对话框面板上的组件的z-index,弹不出来。
  • A:这是版本"element-plus": "1.3.0-beta.3"所致,在"element-plus": "1.3.0-beta.5"已修改。

11. el-upload 缓存清除

  • Q:上传大的视频,采取断点续传结束时,文件列表会残留(如何清除残留成了课题)
  • A:vue3中的清除办法如下
# 定义
const { proxy } = getCurrentInstance();

# 使用
proxy.$refs.upload.clearFiles();

12. 上传文件,附带加参数如何设置

后台:

@PostMapping
@ResponseBody
public AjaxResult test(@RequestPart("file") MultipartFile file,@RequestParam("isNeed") Boolean isNeed){
}

Postman设置

Body

  • file file
  • isNeed boolean false

13. el-input回车刷新画面问题

一般发生此问题,都是有form表单,可以进行组织处理 修改前

<el-form :model="queryParams" >
     <el-form-item label="タイトル" prop="title">
        <el-input
          v-model="queryParams.title"
          placeholder="请输入抬头"
          clearable
          size="small"
          style="width: 240px"
          @keyup.enter="handleQuery"
        />
  
     </el-form-item>
</el-form

修改后

<el-form :model="queryParams" @submit.native.prevent>
     <el-form-item label="タイトル" prop="title">
        <el-input
          v-model="queryParams.title"
          placeholder="请输入抬头"
          clearable
          size="small"
          style="width: 240px"
          @keyup.enter="handleQuery"
        />
  
     </el-form-item>
</el-form

14. 兄弟组件间,如何信息传递?

VUE3中可以使用mitt

bus.js

import mitt from 'mitt'
const bus = mitt();
export default bus;

兄弟组件1

import bus from '@/utils/bus

bus.emit('listenWebsocket',{source: source});

兄弟组件2

import bus from '@/utils/bus'

bus.on('listenWebsocket',data=>{
    if(data.source == 'app'){
        getList();
    }
})
# 组件退出之前,关掉此listenWebsocket
onBeforeUnmount(()=>{
    bus.off('listenWebsocket')
})