学习笔记(2023/06/07开始)

118 阅读5分钟

Web worker

作用:
    为javascript创造多线程环境(允许主线程创造worker线程,将一些任务分配给后者运行),这样的好处是,一些计算密集型或高延迟的任务,被worker线程负担了,主流程就会很流畅,不会被阻塞或延慢。

使用限制:
    1、同源限制:分配给worker线程运行的脚本文件,必须与主线程的脚本文件同源。
    2、文件限制:worker线程无法读取本地文件(file://),会拒绝使用file协议创建worker实例,它所加载的脚本必须来自网络。
    3、DOM操作限制:worker线程所在的全局对象,与主线程不一样,无法读取主线程所在网页的DOM对象,无法使用document,window,parent这些对象
    4、通信限制:worder线程和主线程不在同一个上下文环境,它们不能直接通信,必须通过信息完成。交互的方法分别是postMessage和onmessage,并且在数据传递的时候,worker是使用拷贝的方式。
    5、脚本限制:worker线程不能执行alert()和confirm(),但可以使用ajax请求,setTimeout和setInterval等API。

例:
    Const worker=new Worker(URL, options)
    Worker.postMessage:向worker的内部作用域发送一个消息,消息由任何javascript对象组成。
    Worker.terminate:立即终止worker,该方法并不会等待worker去完成它剩余的操作,将会立即停止。
    Worker.onmessage:当worker的父级接受到来自worker的消息时,会在worker对象上触发message事件
    Worker.onerror:当worker出现运行错误时,它的onerror事件处理函数会被调用,它会收到以扩展了errorEvent接口的名为error的事件

Web worker的执行上下文名称时 self | this,无法调用主线程的window对象的。
worker线程内部要加载其他脚本,可以使用importScripts()

URL对象,创建内嵌的worker。
  <!--  这段代码不会被 JS 引擎直接解析,因为类型是 'javascript/worker' -->
  <script id="worker" type="javascript/worker">
      this.addEventListener('message', (e) => { // Web Worker 的执行上下文名称是 self,无法调用  主线程的 window 对象的
 console.log('wokerEvent', self, e);
      postMessage(`Blob worker线程接收到的消息:::${e.data}`)
      })
      </script>
      <script>
      const blobWorkerScript = document.querySelector('#worker').textContent
      const blob = new Blob([blobWorkerScript], { type'text/javascript' })
      const worker = new Worker(window.URL.createObjectURL(blob))
      </script>

promise

 /**
 * 分段1 => resolve和reject
 * 1. 执行了resole, Promise状态会变成fulfilled
 * 2. 执行了reject, Promise状态会变成rejected
 * 3. Promise状态不可逆, 第一次成功就永久为falfilled, 第一次失败就永远状态为rejected
 * 4. Promise中有throw的话
 */
 class MyPromise {
  constructor(executor) {
    // 初始化值
    this.initValue()
    // 初始化this指向
    this.initBind()
    try {
      // 执行传进来的函数
      executor(this.resolve, this.reject);
    } catch (e) {
      // 捕捉到错误及直接执行reject
      this.reject(e)
    }

  }

  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }

  initValue() {
    this.promiseResult = null; // 最终值
    this.promiseState = 'pending'; // 状态
  }

  resolve(value) {
    // state是不可变的
    if (this.promiseState !== 'pending') return;
    // 如果执行resolve, 状态变为fulfilled
    this.promiseState = 'fulfilled';
    this.promiseResult = value;
  }

  reject(value) {
    // state是不可变的
    if (this.promiseState !== 'pending') return;
    // 如果执行reject,状态变为rejected
    this.promiseState = 'rejected';
    this.promiseResult = value;
  }
}
const p1 = new MyPromise((resolve, reject) => {
  resolve('success');
  reject('fail');
})
/**
 * 分段2 => then
 * 1. then接收两个回调, 一个是成功回调, 一个是失败回调
 * 2. 当Promise状态为fulfilled执行成功回调, 为rejected执行失败回调
 * 3. 如resolve或reject在定时器里, 则定时器结束后再执行then
 * 4. then支持链式调用, 下一次then执行受上一次then返回值的影响
 *    (1) then方法本身会返回一个新的Promise对象;
 *    (2) 如果返回值是promise对象,返回值为成功, 新promise就是成功;
 *    (3) 如果返回值是promise对象,返回值为失败, 新promise就是失败;
 *    (4) 如果返回值是非promise对象,新promise就是成功, 值为此返回值;
 */
 class MyPromise {
  constructor(executor) {
    // 初始化值
    this.initValue()
    // 初始化this指向
    this.initBind()
    try {
      // 执行传进来的函数
      executor(this.resolve, this.reject);
    } catch (e) {
      // 捕捉到错误及直接执行reject
      this.reject(e)
    }

  }

  initBind() {
    this.resolve = this.resolve.bind(this);
    this.reject = this.reject.bind(this);
  }

  initValue() {
    this.promiseResult = null; // 最终值
    this.promiseState = 'pending'; // 状态
    this.onFulfilledCallbacks = []; // 保存成功回调
    this.onRejectedCallbacks = []; // 保存失败回调
  }

  resolve(value) {
    // state是不可变的
    if (this.promiseState !== 'pending') return;
    // 如果执行resolve, 状态变为fulfilled
    this.promiseState = 'fulfilled';
    this.promiseResult = value;
    // 执行保存的成功回调
    while (this.onFulfilledCallbacks.length) {
      this.onFulfilledCallbacks.shift()(this.promiseResult)
    }
  }

  reject(value) {
    // state是不可变的
    if (this.promiseState !== 'pending') return;
    // 如果执行reject,状态变为rejected
    this.promiseState = 'rejected';
    this.promiseResult = value;

    while (this.onRejectedCallbacks.length) {
      this.onRejectedCallbacks.shift(this.promiseResult);
    }
  }

  // 接收两个回调onFulfilled onRejected
  then(onFulfilled, onRejected) {
    // 参数校验,确保一定是函数(如果为非函数, 则将其包装)
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

    // 这里用const来声明thenPromsie,在验证x === thenPromise时会卡住,原因还未知
    var thenPromise = new MyPromise((resolve, reject) => {

      const resolvePromise = cb => {
        // 可在这儿添加一个setTimeout模拟宏任务
        try {
          var x = cb(this.promiseResult);
          /**
           * 不能返回自身
           * 每次调用then会生成一个新的MyPromise对象, 如果最终还是以该promise对象作为结果返回,
           * 则报错
           */
          if (x === thenPromise && x) {
            throw new Error('不能返回自身')
          }
          // 验证结果是否为Promise对象
          if (x instanceof MyPromise) {
            x.then(resolve, reject);
          } else {
            // 非Promise对象则直接成功,将该值作为结果传递过去
            resolve(x)
          }
        } catch (err) {
          // 处理报错
          reject(err)
          throw new Error(err)
        }
      }

      // 若为成功状态,执行第一个回调
      if (this.promiseState === 'fulfilled') {
        resolvePromise(onFulfilled)
      } else if (this.promiseState === 'rejected') {
        // 如果当前为失败状态,执行第二个回调
        resolvePromise(onRejected)
      } else if (this.promiseState === 'pending') {
        // 如果状态为待定状态, 暂时保存两个回调
        this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled));
        this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected));
      }
    })

    return thenPromise
  }
}
// then返回promise
const p3_1 = new MyPromise((resolve, reject) => {
  resolve(10)
}).then(res => {
  return new MyPromise((resolve, reject) => {
    resolve(res * 10)
  })
}).then(res => {
  console.log('last==', res) // 200
})
// then返回非promise
const p3_2 = new MyPromise((resolve, reject) => {
  resolve(10)
}).then(res => {
  return res * 2
}).then(res => {
  console.log('last222==', res) // 20
})

// then返回自身
const p3_3 = new MyPromise((resolve, reject) => {
  resolve(10)
}).then(res => {
  return p3_3
}).then(res => {
  console.log('last222==', res) 
}, e => console.log('error', e)) // 执行error

promise方法

/**
 * ? all
 * 1. 接收一个Promise数组, 数组中如有非Promise项, 则此项当做成功
 * 2. 如果所有Promise都成功, 则返回成功结果数组
 * 3. 如果有一个Promise失败, 则返回这个失败结果
 */
// Promise.all([p1, p3]).then((res) => {
//   console.log('res==', res)
// }).catch(e => console.log(e))


/**
 * ? race
 * 1. 接收一个Promise数组, 数组中如有非Promise项, 则此项当做成功;
 * 2. 哪个Promise最快得到结果, 就返回哪个结果, 无论成功失败
 */
// Promise.race([p1, p2, p3]).then((res) => console.log(res)).catch(e => console.log(e))

/**
 * ? allSettled
 * 1. 接收一个Promise数组, 数组中如有非Promise项, 则此项当做成功
 * 2. 把每一个Promise的结果, 集合成数组后返回
 */
// Promise.allSettled([p1, p2, p3]).then((res) => console.log(res)).catch(e => console.log(e))


/**
 * ? any 与all相反
 * 1. 接收一个Promise数组, 数组中如有非Promise项, 则此项当做成功
 * 2. 如果有一个Promise成功, 则返回这个成功结果
 * 3. 如果所有Promise都失败, 则报错
 */
Promise.any([p1, p2, p3]).then((res) => console.log('any', res)).catch(e => console.log(e))