zf-总结

zf-总结,第1张

docker linux点滴yan nginx点滴yan py点滴yan 设计模式 AOP (装饰模式) 将函数进行包装 (代理模式) before after

AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,其实就是给原函数增加一层,不用管原函数内部实现

发布订阅模式 观察者模式 (events on emit) ,基于发布订阅模式 promise Promise 解决的问题
1. 回调嵌套 回调地狱
2. 错误捕获不好处理错误
3. 多个异步同步的问题 Promise.all,还是基于回调的方式的
Promise的特点
1. Promise的概念 规范文档 promise A+ 规范
2. Promise 三个状态 等待 成功态 失败态
3. 只有等待态 才能变成成功 / 失败
4. 如果状态变化后不能在修改状态
promise-1 编码 三个状态,then方法实现,一个value和reason。

const SUCCESS = 'fulfilled'
const FAIL = 'rejected';
const PENDING = 'pending'
class Promise {
  constructor(executor) {
    this.status = PENDING; // 默认是等待态
    this.value= undefined;
    this.reason = undefined
    let resolve = (value) => {
        if(this.status === PENDING){
            this.value = value;
            this.status = SUCCESS;
        }
    };
    let reject = (reason) => {
        if(this.status === PENDING){
            this.reason = reason;
            this.status = FAIL;
        }
    };
    executor(resolve,reject);
  }
  then(onFulfilled,onRejected){
    if(this.status === SUCCESS){
        onFulfilled(this.value);
    }
    if(this.status === FAIL){
        onRejected(this.reason);
    }
  }
}
module.exports = Promise;
promise-2 promise不是同步的时候数组存放。错误的时候。trycatch.
const SUCCESS = 'fulfilled'
const FAIL = 'rejected';
const PENDING = 'pending'
class Promise {
  constructor(executor) {
    this.status = PENDING; // 默认是等待态
    this.value= undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = []; // 存储成功的所有的回调 只有pending的时候才存储
    this.onRejectedCallbacks = []; // 存储所有失败的
    let resolve = (value) => { // 成功
        if(this.status === PENDING){
            this.value = value;
            this.status = SUCCESS;
            this.onResolvedCallbacks.forEach(fn=>fn());
        }
    };
    let reject = (reason) => { // 失败
        if(this.status === PENDING){ 
            this.reason = reason;
            this.status = FAIL;
            this.onRejectedCallbacks.forEach(fn=>fn());
        }
    };
    try{
        executor(resolve,reject);
    }catch(e){
        reject(e);
    }
  }
  then(onFulfilled,onRejected){ // 默认看一下状态调用对应的函数
    if(this.status === SUCCESS){
        onFulfilled(this.value);
    }
    if(this.status === FAIL){
        onRejected(this.reason);
    }
    if(this.status === PENDING){
        this.onResolvedCallbacks.push(()=>{
            onFulfilled(this.value);
        });
        this.onRejectedCallbacks.push(()=>{
            onRejected(this.reason);
        })
    }
  }
}
module.exports = Promise;

promise-3 编码 必须返回一个Promise
const PENDING = "PENDING";
const SUCCESS = "FULFILLED";
const FAIL = "REJECTED";
// 返还的那个新的promise x 是then方法中的返回值 
function resolvePromise(promise2, x,resolve,reject) { // 考虑的非常全面
    if(promise2 === x){
       return reject(new TypeError('TypeError: Chaining cycle detected for promise #'));
    }
    // 判断x的类型
}
class Promise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = value => {
      if (this.status === PENDING) {
        this.value = value;
        this.status = SUCCESS;
        this.onResolvedCallbacks.forEach(fn => fn());
      }
    };
    const reject = reason => {
      if (this.status === PENDING) {
        this.reason = reason;
        this.status = FAIL;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (e) {
      console.log(e);

      reject(e);
    }
  }
  // 同一个promise then 多次
  then(onFulfilled, onRejected) {
    let promise2;
    // 可以不停的调用then方法,返还了一个新的promise
    // 异步的特点 等待当前主栈代码都执行后才执行
    promise2 = new Promise((resolve, reject) => {
      if (this.status === SUCCESS) {
        setTimeout(() => {
          try {
            // 调用当前then方法的结果,来判断当前这个promise2 是成功还是失败
            let x = onFulfilled(this.value);
            // 这里的x是普通值还是promise
            // 如果是一个promise呢?
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            console.log(err);
            reject(err);
          }
        });
      }
      if (this.status === FAIL) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            console.log(err);
            reject(err);
          }
        });
      }
      if (this.status === PENDING) {
        this.onResolvedCallbacks.push(()=>{
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (err) {
              console.log(err);
              reject(err);
            }
          });
        });
        this.onRejectedCallbacks.push(()=> {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (err) {
                console.log(err);
              reject(err);
            }
          });
        });
      }
    });
    return promise2;
  }
}

module.exports = Promise;
promise-4 resolvePromise按照promise 加规范实现。
function resolvePromise(promise2, x,resolve,reject) { // 考虑的非常全面
    if(promise2 === x){
       return reject(new TypeError('TypeError: Chaining cycle detected for promise #'));
    }
    // 判断x的类型
    // promise 有n种实现 都符合了这个规范 兼容别人的promise

    // 怎么判断 x是不是一个promise 看他有没有then方法
    if(typeof x === 'function' || (typeof x === 'object' && x != null)){
      try{
        let then = x.then; // 去then方法可能会出错
        if(typeof then === 'function'){ // 我就认为他是一个promise
           then.call(x,y=>{ // 如果promise是成功的就把结果向下传,如果失败的就让下一个人也失败
              resolvePromise(promise2,y,resolve,reject); // 递归
           },r=>{
              reject(r);
           }) // 不要使用x.then否则会在次取值
        }else{ // {then:()=>{}}
          resolve(x);
        }
      }catch(e){
        reject(e);
      }
    }else{ // x是个? 常量 
      resolve(x);
    }
}
promise-5 当执行过的时候不能再执行,called,值穿透的问题
const PENDING = "PENDING";
const SUCCESS = "FULFILLED";
const FAIL = "REJECTED";
// 严谨 🇬应该判断 别人的promise 如果失败了就不能在调用成功 如果成功了不能在调用失败
function resolvePromise(promise2, x,resolve,reject) { 
    if(promise2 === x){
       return reject(new TypeError('TypeError: Chaining cycle detected for promise #'));
    }
    let called;
    if(typeof x === 'function' || (typeof x === 'object' && x != null)){
      try{
        let then = x.then;  // then 可能是getter object.defineProperty
        if(typeof then === 'function'){  // {then:null}
           then.call(x,y=>{ 
             if(called) return; // 1)
             called = true;
              resolvePromise(promise2,y,resolve,reject); 
           },r=>{
             if(called) return; // 2)
             called = true;
              reject(r);
           }) 
        }else{ 
          resolve(x);
        }
      }catch(e){
        if(called) return; // 3) 为了辨别这个promise 不能调用多次
        called = true;
        reject(e);
      }
    }else{
      resolve(x);
    }
}
class Promise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = value => {
      if (this.status === PENDING) {
        this.value = value;
        this.status = SUCCESS;
        this.onResolvedCallbacks.forEach(fn => fn());
      }
    };
    const reject = reason => {
      if (this.status === PENDING) {
        this.reason = reason;
        this.status = FAIL;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }
  then(onFulfilled, onRejected) { // .catch(function(){}) .then(null,function)
  onFulfilled = typeof onFulfilled === 'function'?onFulfilled:val=>val;
  onRejected =  typeof onRejected === 'function'?onRejected:err=>{throw err}
    let promise2;
    promise2 = new Promise((resolve, reject) => {
      if (this.status === SUCCESS) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      }
      if (this.status === FAIL) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (err) {
            reject(err);
          }
        });
      }
      if (this.status === PENDING) {
        this.onResolvedCallbacks.push(()=>{
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (err) {
              reject(err);
            }
          });
        });
        this.onRejectedCallbacks.push(()=> {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (err) {
              reject(err);
            }
          });
        });
      }
    });
    return promise2;
  }
}
// 希望测试一下这个库是否符合我们的promise A+规范
// promises-aplus-tests
Promise.defer = Promise.deferred = function(){
  let dfd = {};
  dfd.promise = new Promise((resolve,reject)=>{
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
}
module.exports = Promise;
// npm i promises-aplus-tests -g
// promise 相关方法
// generator
Promise相关方法补充
let p = new Promise((resolve,reject)=>{
    resolve();
})
// 1).中断promise链 就是返回一个等待的promise
let p1 = p.then(()=>{
    console.log('ok');
    return new Promise(()=>{})
}).then(()=>{
    console.log(1);
})

// 2.finally 实现
Promise.prototype.finally = function(callback){
    // callback 直接放到失败里 会导致无法继承上一次的失败
    // return this.then(callback,callback);
    return this.then((val)=>{
        // 等待finally中的函数执行完毕 继续执行 finally函数可能返还一个promise 用Promise.resolve等待返回的promise执行完
        return Promise.resolve(callback()).then(()=>val);
        //return val; // 如果上一个then是成功就将这个成功向下传递
    },(err)=>{
        return Promise.resolve(callback()).then(()=>{throw err});
        //throw err; // 如果上一个then是失败就将这个失败继续向下抛
    })
}
Promise.reject().finally(()=>{
    console.log(1);
    return new Promise((resovle,reject)=>{
        setTimeout(() => {
            resovle();
        }, 1000);
    })
}).catch(e=>{
    console.log(e);
})

// 3) race 赛跑 哪个快 用哪个 all是所有完成才完成

let p1 = new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve('ok1');
    }, 1000);
})
let p2 = new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve('ok2');
    }, 2000);
})
Promise.race = function(promises){
    return new Promise((resolve,reject)=>{
        for(let i = 0;i<promises.length;i++){
            promises[i].then(resolve,reject); // 只要一个成功就成功
        }
    })
}
Promise.race([p1,p2]).then(data=>{
    console.log(data)
});
// 我有一个网站有一个接口 在两个服务器上

// 4)如何放弃某个promise的执行结果
function wrap(p1){
    let fail = null;
    let p2 = new Promise((resolve,reject)=>{
        fail = reject; // 先将p2失败的方法暴露出来 
    });
    let p = Promise.race([p2,p1]); // race方法返回的也是一个promise
    p.abort = fail;
    return p
    
}
let p = wrap(new Promise((resolve,reject)=>{
    setTimeout(() => {
        resolve('ok');
    }, 3000);
}))
p.abort('error');
p.then(data=>{
    console.log(data);
}).catch(err=>{
    console.log(err);
});
// 5)既能捕获同步有能捕获异步

function fn(){
    // 可能函数中抛出了 同步错误 要通过try-catch 捕获异常
    // throw new Error('err');
    //    return new Promise((resolve,reject)=>{
    //        setTimeout(() => {
    //         reject('xxx');
    //        }, 3000);
    //    })
}
Promise.try = function(callback){
    return new Promise((resolve,reject)=>{
        // Promise.resolve 只能返回一个成功的promise
        return Promise.resolve(callback()).then(resolve,reject);
    })
}
Promise.try(fn).then((data)=>{
    console.log(data,'---');
},err=>{
    console.log('err:'+err);
}); 

var const let 的区别和联系
1. var 声明的变量默认声明到全局上,let 作用域, 实现一个作用域
2. 用var 声明的变量会导致变量提升 var function, 用let声明的变量会绑定到当前作用域  暂存死区。
3. var 命令的变量可以重复; 使用let 可以保证我的代码命名不重复。
4. var 声明的变量可以更改,let也行,但是const不行。
set 和map 是es6中新的数据类型 都不能放重复的

Map是键值对,Set是值的集合,当然键和值可以是任何的值

let set = new Set([1,2,3,3,2,1])
set.keys()
set.values()
set.entries()
set.clear()
set.delete()
set.has
------
let map = new Map(); // hash 表
map.set({a:1},123);
map.set('bbq',456);
console.log(map)
Object.defineProperty
let obj = {}
let val = '';
Object.defineProperty(obj,'a',{
    configurable:true, // 是否可删除
    // writable:true, // 是否可写,
    enumerable:true, // for in 原型上的方法
    get(){
        return val
    },
    set(value){
        val = value;
    }
    // 默认设置的值是不可枚举的
})
Reflect

Object.defineProperty里面有部分的对象的方法 放到 Reflect 功能基本一致
Proxy 中能代理的方法 Reflect 都可以实现

1. get /set
Reflect.set(obj,'name','zf'); // obj.name = zf;
2. has
Reflect.has({a:1},'a')
3. defineProperty
Reflect.defineProperty(obj,'a',{
    value:100
})
4. getOwnPropertyDescriptor
Reflect.getOwnPropertyDescriptor(obj,'a')
5. ownKeys
let obj = {
    a:1,
    [Symbol()]:1
};
console.log(Object.getOwnPropertyNames(obj));
console.log(Object.getOwnPropertySymbols(obj));
console.log(Reflect.ownKeys(obj))
6. Reflect.setPrototypeOf , Reflect.getPrototypeOf
7. 函数的apply方法 bind call apply
const fn = function(a,b){ // apply 支持多个参数传参
    console.log(this,a,b);
}
Reflect.apply(fn,1,[2,3]); // 用原型上的apply方法
8. construct
class XXX{
    constructor(name){
        this.name = name
    }
}
let xxx =  Reflect.construct(XXX,['zf']);
console.log(xxx); // new
9. deleteProperty
10. preventExtensions
11. isExtensible 
Symbol
Symbol("zf")
Symbol.for("zf")
Symbol.keyFor
// 元编程 可以改变js源代码的功能 改变js原有的功能
Symbol.hasInstance
Symbol.toPrimitive
Symbol.toStringTag
Symbol.species 控制衍生对象的类的构造函数
Symbol.unscopables  不在with中使用
Symbol.isConcatSpreadable
commonjs 和 esModule模块 AMD
esModule的优势
1. es6静态导入,你不能在作用域中使用。
2.  可以将所有属性收集到obj对象中
3. es6导出的是一个引用,而commonjs导出的是一个值的copy。
4. 也可以动态的使用import。当成一个方法使用。
队列 排队 先进先出 栈的特点就是先进后出 代码执行的时候结构就是个栈 (执行上下销毁的时候 是从里向外的) 链表 单向链表 双向链表 循环链表 集合 Set 二叉树 二叉查找树 数据存储方式 小的放左边 大的放右边 图 邻接表 (图 树直接的节点产生了关联就是图) 使用箭头函数应注意什么?
1.用了箭头函数,this就不是指向window,而是父级(指向是可变的)
2、不能够使用arguments对象
3、不能用作构造函数,这就是说不能够使用new命令,否则会抛出一个错误
4、不可以使用yield命令,因此箭头函数不能用作 Generator 函数
浏览器的事件环eventLoop 微任务: promise.then ,MutationObserver,宏任务:script ,ajax , 事件,requestFrameAnimation, setTimeout ,setInterval ,setImmediate (ie下),MessageChannel ,UI rendering。

浏览器的事件eventLoop 和 node 11 版本 表现和浏览器一致
而Vue.$nextTick
先查看你是否支持promoise, 用Promise.resolve。
MutationObserver
setImmediate // 只在ie下采用
setTimeout

node的事件环eventLoop

node的微任务 process.nextTick
node的宏任务又分为六个阶段

    ┌───────────────────────┐
┌─> │        timers         │ 本阶段执行setTimeout() 和 setInterval() 
│   └──────────┬────────────┘
│   ┌──────────┴────────────┐
│   │     I/O callbacks     │ 这个阶段执行一些诸如TCP错误之类的系统 *** 作的回调
│   └──────────┬────────────┘
│   ┌──────────┴────────────┐
│   │     idle, prepare     │ 只内部使用
│   └──────────┬────────────┘      ┌───────────────┐
│   ┌──────────┴────────────┐      │   incoming:   │
│   │         poll          │  <───┤  connections, │ 获取新的 I/O 事件,查找已经到时的定时器
│   └──────────┬────────────┘      │   data, etc.  │
│   ┌──────────┴────────────┐      └───────────────┘
│   │        check          │ setImmediate()
│   └──────────┬────────────┘
│   ┌──────────┴────────────┐
└──-┤    close callbacks    │ 关闭事件的回调 socket.close事件
    └──────────────────────—┘
进程,线程

线程是 *** 作系统能够进行运算调度的最小单位, 一个进程可能有多个线程,如果一个线程死亡,那么会影响同进程其他线程的死亡。
一个进程中可以有多个线程,比如渲染线程、JS 引擎线程、HTTP 请求线程等等,进程表示一个程序,线程是进程中的单位 主线程只有一个。
1个进程可以占用1核cpu。
多线程在单核cpu中其实也是顺序执行的,不过系统可以帮你切换那个执行而已,没有提高速度。
多个cpu的话就可以在多个cpu中同时执行。
单线程优点:解决切换上下文时间,锁的问题,节省内存 (多线程)
node 主进程,在开多个子进程,里面包含着一个线程

node进程管理 npm安装

本地安装
全局安装 (bin) 比如:npm i http-server -g

全局安装之后会有软链接
/usr/local/bin/http-server -> /usr/local/lib/node_modules/http-server/bin/http-server
/usr/local/bin/hs -> /usr/local/lib/node_modules/http-server/bin/http-server
我要写一个全局包,npm link链接,创建快捷方式指向我的文件
"bin": {
    "lesson-zf": "./bin/www",
    "lz":"./bin/www"
},
而当npm link执行后,
/Users/dance/.npm-global/bin/lesson-zf -> /Users/dance/.npm-global/lib/node_modules/lesson-zf/bin/www
/Users/dance/.npm-global/bin/lz -> /Users/dance/.npm-global/lib/node_modules/lesson-zf/bin/www
/Users/dance/.npm-global/lib/node_modules/lesson-zf -> /Users/dance/Desktop/珠峰-2019-06-整理/我学习老的代码1/10.npm1
npm版本问题

npm采用了semver规范作为依赖版本管理方案。semver 约定一个包的版本号必须包含3个数字

MAJOR 对应大的版本号迭代,做了不兼容旧版的修改时要更新 MAJOR 版本号MINOR 对应小版本迭代,发生兼容旧版API的修改或功能更新时,更新MINOR版本号PATCH 对应修订版本号,一般针对修复 BUG 的版本号
range含义
^2.2.1指定的 MAJOR 版本号下, 所有更新的版本匹配 2.2.3, 2.3.0; 不匹配 1.0.3, 3.0.1
~2.2.1指定 MAJOR.MINOR 版本号下,所有更新的版本匹配 2.2.3, 2.2.9 ; 不匹配 2.3.0, 2.4.5
>=2.1版本号大于或等于 2.1.0匹配 2.1.2, 3.1
<=2.2版本号小于或等于 2.2匹配 1.0.0, 2.2.1, 2.2.11
1.0.0 - 2.0.0版本号从 1.0.0 (含) 到 2.0.0 (含)匹配 1.0.0, 1.3.4, 2.0.0

预发版:

alpha(α):预览版,或者叫内部测试版;一般不向外部发布,会有很多bug;一般只有测试人员使用。beta(β):测试版,或者叫公开测试版;这个阶段的版本会一直加入新的功能;在alpha版之后推出。rc(release candidate):最终测试版本;可能成为最终产品的候选版本,如果未出现问题则可发布成为正式版本。 常见的依赖项

dependcies
devDepencies
npm install --production 可以只安装dependcies
peerDependencies 会提示你安装缺少的模块 默认要求带版本
bundleDependencies npm pack
optionalDependencies 如果找不到 不会影响npm的下载

本地安装
npm install jquery --save / -S
npm install webpack --save-dev / -D
默认不给–save表示安装到当前的dependencies 表示是上线和开发的时候都需要
devDependencies 开发依赖 上线的时候不需要
有一天把模块发布了 别人会安装你的发布的模块,如果你的模块被别人安装,你的模块中的dependencies会默认一起下载,devDependencies不会下载的
scripts

scripts 配置执行的脚本
即时没有全局安装mime, 但是只要node_modules下边有。当时在npm run test 也是可以执行mime的全局命令的,因为当执行npm run 的时候 他会把当前目录node_modules/.bin也拷贝到当前的系统的path中,所以npm run 可以执行.bin下的文件/

 "scripts": {
      "test": "mime"
  },
npx

可以直接执行node_modules/.bin文件 不需要在去配置scriprts
如果模块不存在可以安装 ,安装完是有后还会自己销毁,避免安装全局模块
npx create-react-app project-name

发布包

npm publish

nrm nvm npm可以切换源

npm install nrm -g
nrm use npm

协议问题

node process, argv, env, module node中的全局对象
## 核心模块 node自带的模块
process,buffer
process.cwd()  process.nextTick process.pid process.argv commander process.env 环境变量
require,exports,module,__filename,__dirname (可以直接在模块内部被访问)
events(on, off, emit, once)
path(path.resolve(__dirname,'./note.md'))
fs
- util util.inherits
-      util.promisify
- buffer(from,alloc,slice,sBuffer)
------------------------util.inherits
function Parent(){}
function Child(){
    Parent.call(this);
}   
// 只继承公共方法
方法1: Child.prototype.__proto__ = Parent.prototype;
方法2: Reflect.setPrototypeOf(Child.prototype,Parent.prototype);
方法3: Child.prototype = Object.create(Parent.prototype);
方法4: util.inherits(Child,Parent); // 继承公共属性
------------------------util.inspect可以显示隐藏属性
console.log(util.inspect(Array.prototype,{showHidden:true}));
console.log(util.isPrimitive); // Symbol
------------------------node首错改为then
let ncp = require('ncp');
let path = require('path');
let util = require('util');
// cp -r
const promisify = fn => (...args)=>{
    return new Promise((resolve,reject)=>{
        fn(...args,function(err){ // 只针对node  因为node是这种error-first的形式
            if(err) reject(err);
            resolve();
        });
    })
}
ncp = promisify(ncp);
(async ()=>{
    await ncp(path.resolve(__dirname,'note.md'),path.resolve(__dirname,'note1.md'));
    console.log('拷贝成功')
})();
编码

ASCII(美国) 默认 就一个一个字节来表示是一个字母或者符号,1个字节 有8个bit 最大 是 8个1 => 10进制 255
gbk 用两个字节来表示中文
base64就是编码转化 不需要发送http请求。大小会比以前大
gb2312 第一位大于127的我认为+ 第二位 就是一个中文 255 - 127 * 255
utf8 中文采用3个字节来表示,node里默认值支持utf8格式,可以采用别的模块来实现。

let str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
str+= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.toLowerCase();
str+= '0123456789+/'
进制转换

(0xff).toString(2)
将任意进制转化成10进制 parseInt(‘0xff’, 16);

fs
64k以下的文件
fs.readFile,fs.writeFile
64k以上的文件
fs.open,fs.read,fs.write
-----
fs.appendFileSync('1.js','123')
fs.writeFileSync('1.js','123',{flag:'a'})
#### 文件的 *** 作
fs.readFile  fs.existSync fs.access
fs.writeFile fs.copyFile
fs.rename fs.unlink  增删改查
#### 文件夹的 *** 作
mkdir rmdir readdir  创建目录  删除目录  读取目录
isFile 
#### 
fs.createReadStream
fs.createWriteStream
缓存

service worker
强制缓存和对比缓存 memory缓存 disk缓存(大文件放到disk中,或者内存使用太高也放到disk中),
pwa service worker缓存,html5离线缓存
HTTP/2中的内容

如果设置强制缓存 首页是不会缓存的,访问的页面如果有强制缓存 则不会在发起请求
res.setHeader(‘Cache-Control’, ‘max-age=10’)。
// 旧的缓存 Expires
res.setHeader(‘Expires’,new Date(Date.now()+10*1000).toGMTString());
// 新的对比缓存 Etag ifModifiedSince
ifNoneMatch !== Etag || ifModifiedSince !== lasModified

加密算法
const crypto = require('crypto');

crypto.createHash('md5').update(r).digest('base64')
crypto.createHmac('sha1','ke1').update('123456').digest('base64')
--- md5 加密
1. 不可逆
2. 相同内容摘要的结果相同,有一点不同出来的结果完全不同
3. 摘要的结果长度相同
压缩方法

zlib.createGzip()
zlib.createDeflate()
gzip压缩 重复率越高 压缩越高

response.setHeader('Content-Encoding','gzip');
raw.pipe(zlib.createGzip()).pipe(response);
协议分层(OSI协议分层)

(物,数),网,传,(会,表,应)

应用层 HTTP,FTP,DNS (与其他计算机进行通讯的一个应用服务,向用户提供应用服务时的通信活动)

传输层 TCP(可靠) UDP 数据传输 (HTTP -> TCP DNS->UDP),TLS与SSL

网络层 IP 选择传输路线 (通过ip地址和mac地址)(使用ARP协议凭借mac地址进行通信)

链路层 网络连接的硬件部分

tcp的三次握手和四次挥手

http://blog.csdn.net/whuslei/article/details/6667471

HTTP特点 http是不保存状态的协议,使用cookie来管理状态 (登录 先给你cookie 我可以看一下你有没有cookie)为了防止每次请求都会造成无谓的tcp链接建立和断开,所以采用保持链接的方式 keep-alive以前发送请求后需要等待并收到响应,才能发下一个,现在都是管线化的方式 (js css 可以并发请求 6 2) cdn HTTP缺点

通信采用明文

不验证通信方的身份

无法验证内容的完整性 (内容可能被篡改)

通过SSL(安全套阶层)建立安全通信线路 HTTPS (超文本传输安全协议)

HTTP方法 (get post 简单请求) Resful风格

GET:获取资源 /user?

POST:传输实体主体 请求体中

PUT:来传输文件

HEAD: 获取报文首

DELETE: 删除文件

OPTIONS:询问支持的方法 跨域 如果默认发送的是get/post 不会发送options的 ““复杂请求””

get /post (a:1) headers:{a:1} put / delete 复杂的请求

REST API Resful风格 根据路径和不同的方法 就能确定对资源进行什么 *** 作

跨域是浏览器之前的 服务器之间没有跨域问题 反向代理 、后端设置cors

c.com-> d.com OPTIONS 非简单请求会发送options (options 直接返回ok就可以了)

HTTP状态码 (发请求 命令行 curl命令) 服务端

curl命令行工具 postman

1xx 信息性状态码 websocket upgrade

2xx 成功状态码 200 204(没有响应体) 206(范围请求 暂停继续下载) 获取网页的部分请求

3xx 重定向状态码 301 302 303 post -> get 304(删除报文主体 在次发送请求) 307 (不会从POST转为GET)

4xx 客户端错误状态码 400 401 403 404 405 方法不允许

5xx 服务端错误状态码 500 503

URI和URL

URI(Uniform Resource Identifier)是统一资源标识符,在某个规则下能把这个资源独一无二标示出来,比如人的身份z号
统一资源定位符,表示资源的地点,URL时使用浏览器访问WEB页面时需要输入的网页地址

报文应用

Content-Encoding : gzip压缩 form-data: 多部分对象集合 上传文件

range: 范围请求 206 accept-language:内容协商 前端控制 后端控制

host:单主机多域名 304 http缓存

referer:访问来源 防盗链 proxy:代理、网关和隧道

user-agent:用户内核 安全相关的头: X-Frame-Options、X-XSS-Protection (安全 csrf xss https 加密)

HTTP相关Header内容 缓存Header 强:Cache-Control && Expires对比:Last-Modified & If-Modified-Since / ETag & If-None-Match 跨域:Access-Control压缩:Content-Encoding : gzip范围请求:range防盗链:referer (防止盗用链接)用户内核:user-agent单主机多域名:host多语言:accept-language文件上传:Content-Type:multipart/form-data文件下载:Content-Description http https的区别和联系。
https:  利用对称加密和非对称加密。
过程: 用户aaa访问某网站xxx
1. aaa发起请求到xxx网站。
2. xxx返回了自己的公钥ggg和一些信息。
3. aaa拿到这些信息去Ac权威机构证明一下(后边讲这个不被窃取的原理,这里其实是本地校验并未去ca机构认证,点下边的链接)。
4. Ac告诉aaa这个公钥和信息对得上,是正确的。
5. aaa自己生成一个私钥sss,然后用这个公钥ggg加密这个私钥发给xxx.
6. 只有xxx的私钥可以解开这个公钥ggg的信息获取到这个私钥sss。
7. 然后aaa和xxx之间的联系就是用这个私钥sss加密.
#### 分析 如果aaa和xxx之间存在代理服务器ttt,如果保证ttt解密不了这些数据。
1. aaa用xxx的公钥ggg加密私钥sss,这个信息只有xxx网站自己的私钥可以解密。即使ttt获取到了,因为不知道ggg对应的私钥无法解密。所以私钥ggg永远无法获取到sss,永远不知道他们之间在说什么。
#### 分析 代理服务器ttt为什么不能在aaa获取证书ggg和aaa从Ac求证的过程中做手脚呢。
1. Ac的私钥浏览器都有内置的。利用Ac加密的信息只有Ac的公钥可以解密。这样ttt永远不知道用户aaa在和ac之间传递的什么信息。
2. 而当Ac浏览器返回信息ok,ok的时候,虽然代理服务器ttt知道说的ok但是永远不知道在说什么是ok的。
http2
目标:改善用户在使用Web时的速度体验。
主要基于SPDY协议。它是Google开发的基于TCP协议的应用层协议。目标是优化HTTP协议的性能,通过压缩、多路复用和优先级 等技术,缩短网页的加载时间并 提高安全性。SPDY协议的核心思想是尽量减少TCP连接数。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。
特点:
1. 二进制传输:二进制帧层,指HTTP消息在客户端和服务端如何封装和传输。与HTTP1.x的采用的换行符分隔文本不同,HTTP/2 消息被分成很小的消息和frame,然后每个消息和frame用二进制编码。
2. 多路复用:所谓多路复用,即在一个TCP连接中存在多个流,即可以同时发送多个请求。在客户端帧乱序发送,到对端后再根据每个帧首部的流标识符重新组装。
3. Header压缩:使用 HPACK(HTTP2头部压缩算法)压缩格式对传输的header进行编码。并在两端维护了索引表,用于记录出现过的header,后面在传输过程中就可以传输已经记录过的header的键名,对端收到数据后就可以通过键名找到对应的值。
4. 服务器推送:在 HTTP2.0 中,服务端可以在客户端某个请求后,主动推送其他资源。
多语言

// Accept-Language: zh-CN;q=1,zh;q=0.9,en;q=0.8
// 客户端可以自行配置语言 .不同的语言组成不同的网站

跨域 博客2

其实CORS和Access-Control-Allow-Origin的方式是一样的,都是需要后端对应的处理的。
1.通过jsonp跨域
2.通过iframe跨域
(1)只通过iframe展示界面,不进行父子页面间的数据传递。
(2)进行父子页面的数据传递。要求父和子必须有相同的主域名,并且设置document.domain相同,
这个时候有三种方法交换数据:
a.父通过id或者子通过.parent之类的方法
b.通过cookie传递值。
3. window.name来进行跨域

4.使用HTML5中新引进的window.postMessage方法来跨域传送数据

5.CORS 需要服务器设置header :Access-Control-Allow-Origin。
6.nginx反向代理 这个方法一般很少有人提及,但是他可以不用目标服务器配合,不过需要你搭建一个中转nginx服务器,用于转发请求

本地储

localStorage,sessionStorage,session,cookie,indexDB,cacheApi

defer & async / preload & prefetch defer 和 async 在网络读取的过程中都是异步解析defer是有顺序依赖的,async只要脚本加载完后就会执行preload 可以对当前页面所需的脚本、样式等资源进行预加载 vue 路由懒加载prefetch 加载的资源一般不是用于当前页面的,是未来很可能用到的这样一些资源 Koa

洋葱的中间件模型
koa的中间件模式与express的是不一样的,koa是洋葱型,express是直线型
核心的四个文件
Application,context, request, response
把所有的属性挂到context上边,contest挂到response上,request上。

app.listen
app.handleRequest
app.compose
const logger = ()=>{
    return new Promise((resolve,reject)=>{
      setTimeout(() => {
        console.log('logger');
        resolve(); 
      }, 1000);
    })
}
app.use(async (ctx,next)=>{ // 上下文
  await logger();
  return next();
});

// Koa路由 routes
app.use(index.routes(), index.allowedMethods())
app.use(users.routes(), users.allowedMethods())

express 应用
const express = require('./express');
const path = require('path');
// 模板引擎 koa-views
const app = express();
app.set('views','view'); // 将默认的存放路径更改
app.set('view engine','.html');// 默认使用可以使用html文件

app.engine('.html',require('ejs').__express);//如果遇到.html用ejs来渲染
app.get('/',function(req,res){
   console.log(req.a)
   res.sendFile(path.resolve(__dirname,'package.json'))
   // res.send(301);
})

app.listen(3000);
前后端交互的几种方式

application/x-www-form-urlencoded
multipart/form-data(文件上传)
application/json

webpack 作用

代码转换, 文件优化, 代码分割,模块合并,自动刷新,代码校验,自动发布

webpack核心概念

Entry:入口
Module:模块
Chunk:代码块
Loader:模块转换器
Plugin:扩展插件
Output:输出结果

常用的配置

devServer:配置开发服务器
mode:development,production

loader

css-loader
style-loader
file-loader
url-loader 当图片小于limit的时候会把图片BASE64编码,大于limit参数的时候还是使用file-loader 进行拷贝
html-withimg-loader
postcss-loader autoprefixer

插件

html-webpack-plugin

+       new HtmlWebpackPlugin({
+            template:'./src/index.html',//指定模板文件
+            filename:'index.html',//产出后的文件名
+            inject:false,
+            hash:true,//为了避免缓存,可以在产出的资源后面添加hash值
+            chunks:['common','index'],
+            chunksSortMode:'manual'//对引入代码块进行排序的模式
+        }),

mini-css-extract-plugin 分离CSS
terser-webpack-plugin 压缩JS
optimize-css-assets-webpack-plugin 压缩CSS

module.exports = {
    mode: 'production',
    optimization: {
        minimizer: [
           /*  new UglifyJsPlugin({
                cache: true,//启动缓存
                parallel: true,//启动并行压缩
                //如果为true的话,可以获得sourcemap
                sourceMap: true // set to true if you want JS source maps
            }), */
            new TerserPlugin({
                 parallel: true,
                 cache: true
            }),
            //压缩css资源的
            new OptimizeCSSAssetsPlugin({
                 assetNameRegExp:/\.css$/g,
                 //cssnano是PostCSS的CSS优化和分解插件。cssnano采用格式很好的CSS,并通过许多优化,以确保最终的生产环境尽可能小。
                 cssProcessor:require('cssnano')
            })
        ]
    },

outputPath 输出路径
publicPath指定的是构建后在html里的路径

文件指纹

Hash 每次都是新的
chunkhash 入口不变,值不变,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响
contenthash

webpack es6=>es5
babel-loader @babel/core @babel/preset-env  @babel/preset-react
"@babel/plugin-proposal-decorators"
"@babel/plugin-proposal-class-properties"
默认情况下会被添加到每一个需要它的文件中。你可以引入 @babel/runtime 作为一个独立模块,来避免重复引入
babel-plugin-transform-runtime
eslint-loader babel-eslint source-map eval 生成代码 每个模块都被eval执行,每一个打包后的模块后面都增加了包含sourceURLsource-map 产生map文件inline 不会生成独立的 .map文件,会以dataURL形式插入cheap 忽略打包后的列信息,不使用loader中的sourcemapmodule 没有列信息,使用loader中的sourcemap(没有列信息)
devtool:isDev?'cheap-module-eval-source-map':false
打包第三方类库
13.1 直接引入 import _ from 'lodash';
13.2 插件引入
+ new webpack.ProvidePlugin({
+     _:'lodash'
+ })
13.3 expose-loader 
方法1: require("expose-loader?libraryName!./file.js");
方法2: { 
  test: require.resolve("jquery"), 
  loader: "expose-loader?jQuery"
}
方法3: require("expose-loader?$!jquery");
13.4 externals 如果我们想引用一个库,但是又不想让webpack打包,并且又不影响我们在程序中以CMD、AMD或者window/global全局等方式进行使用,那就可以通过配置externals。
+ externals: {
+         jquery: 'jQuery'//如果要在浏览器中运行,那么不用添加什么前缀,默认设置就是global
+ },
13.5 html-webpack-externals-plugin
const htmlWebpackExternalsPlugin= require('html-webpack-externals-plugin');
new htmlWebpackExternalsPlugin({
            externals:[
                {
                    module:'react',
                    entry:'https://cdn.bootcss.com/react/15.6.1/react.js',
                    global:'React'
                },
                 {
                    module:'react-dom',
                    entry:'https://cdn.bootcss.com/react/15.6.1/react-dom.js',
                    global:'ReactDOM'
                }
            ]
}) 
拷贝静态文件 copy-webpack-plugin 打包前先清空输出目录 clean-webpack-plugin 服务器代理 noParse DefinePlugin IgnorePlugin 区分环境变量

生产环境
可能需要分离 CSS 成单独的文件,以便多个页面共享同一个 CSS 文件
需要压缩 HTML/CSS/JS 代码
需要压缩图片
开发环境
需要生成 sourcemap 文件
需要打印 debug 信息
需要 live reload 或者 hot reload 的功能…

多入口MPA

entryFiles + html-webpack-plugin

分析

speed-measure-webpack-plugin
webpack-bundle-analyzer

polyfill libraryTarget 和 library

output.library 配置导出库的名称
output.libraryTarget 配置以何种方式导出库,是字符串的枚举类型

git hooks
"lint-staged": {
    "*": [
      "eden lint",
      "git add"
    ]
  },
"husky": {
    "hooks": {
      "commit-msg": "commitlint .commitlintrc.js -E HUSKY_GIT_PARAMS",
      "pre-commit": "lint-staged"
    }
  },
webpack 优化 purgecss-webpack-plugin去除多余的css DLL 在一个动态链接库中可以包含给其他模块调用的函数和数据 多进程处理 Happypack thread-loader webpack和cdn链接 Tree Shaking 针对js

一个模块可以有多个方法,只要其中某个方法使用到了,则整个文件都会被打到bundle里面去,tree shaking就是只把用到的方法打入bundle,没用到的方法会uglify阶段擦除掉
原理是利用es6模块的特点,只能作为模块顶层语句出现,import的模块名只能是字符串常量

代码分割

多入口
动态导入和懒加载
提取公共代码
{
optimization: splitChunks
}

HMR 提高开发效率 webpack 插件钩子

const {
SyncHook,
SyncBailHook,
SyncWaterfallHook,
SyncLoopHook,
AsyncParallelHook,
AsyncParallelBailHook,
AsyncSeriesHook,
AsyncSeriesBailHook,
AsyncSeriesWaterfallHook
} = require(‘tapable’);
Basic 不关心监听函数的返回值
Bail 保险式: 只要监听函数中有返回值(不为undefined),则跳过之后的监听函数
Waterfall 瀑布式: 上一步的返回值交给下一步使用
Loop 循环类型: 如果该监听函数返回true,则这个监听函数会反复执行,如果返回undefined则退出循环

webpack ast webpack loader

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/944732.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-18
下一篇 2022-05-18

发表评论

登录后才能评论

评论列表(0条)

保存