Promisification+微任务

前提摘要

Promise 对象的构造器(constructor)语法如下:
let promise = new Promise(
    function(resolve, reject) {
        // executor
     }
);
传递给 new Promise的函数被称为 executor当 new Promise 被创建,executor 会自动运行。

一、Promisification

fication:使成为...,Promisification:使……成为promise

node.js常使用,promisify 是Node.js 标准库 util 模块中的一个函数。
作用:将遵循Node.js 回调风格的函数转换为返回Promise 的函数,可以使用 async/await 语法来等待异步操作完成,从而让异步代码看起来更像同步代码。

目的: 接受回调的函数 —————————> 一个 返回promise的函数
用法: loadScript(‘path/script.js’, (err, script) => {…} ) —————————> loadScriptPromise(‘path/script.js’).then(…)
在这里插入图片描述

promisify(f)

针对callback(err, result)只有两个参数的转化(最常用)

  1. 接受一个需要被 promise 化的函数 f,并返回一个包装函数(*)。
  2. 包装器返回一个 promise,并将调用转发给原始的 f,并在我们自定义的回调 (**) 中跟踪结果。
// 目标:
// 1. 返回一个promise,在封装的promise里调用原函数
// 2. 调用promise函数时只传除callback的其他参数,内部调用原函数参数要保持一致(加上callback)

function promisify(f) {
  return function (...args) { // (*)    // ...args:src
    return new Promise((resolve, reject) => {
      function callback(err, result) { // 我们对 f 的自定义的回调 (**)
        if (err) {
          reject(err);
        } else {
          resolve(result);
        }
      }

      args.push(callback); // 将我们的自定义的回调附加到 f 参数args的末尾,args:[src, callback]
      f.call(this, ...args); // 调用原始的函数,
                             // call第一个参数this:调用原始函数时,保留原始函数(f)中对于 this 关键字的引用,保持上下文一致性。
    });
  };
}

// 用法:
let loadScriptPromise = promisify(loadScript); // 返回一个包装函数 *
loadScriptPromise(...).then(...);  // loadScriptPromise传入src

二、微任务

  • 同步代码是指在当前执行上下文中按顺序执行的代码,不涉及异步操作。
    当 JavaScript 引擎执行到同步代码时,会一行一行地顺序执行,不会等待其他代码或事件的完成。
  • 宏任务是指由 JavaScript 引擎放入任务队列中的任务。
    它们通常包括整个脚本、setTimeout、setInterval、DOM 事件等。
    宏任务会在当前执行栈中的所有同步代码执行完毕后才会被执行

异步任务需要管理,ECMA 标准规定了一个内部队列 PromiseJobs,通常被称为 “微任务队列(microtask queue)”

  • 队列(queue)先进先出
  • 只有在 JavaScript 引擎中没有其它任务在运行时,才开始执行任务队列中的任务。

示例1

promise 的处理程序 .then、.catch 和 .finally 都是异步的。 当一个 Promise 准备就绪(即状态变为 resolved 或 rejected)时
它的 .then()、.catch()、.finally() 等处理程序会被放入微任务队列中。

let promise = Promise.resolve();

promise.then(() => alert("promise done!")); // 放进微任务队列

alert("code finished"); // 这个 alert 先显示

解析:

  1. let promise = Promise.resolve();
    创建了一个已经 resolved 的 Promise 对象。
  2. promise.then(() => alert("promise done!"));
    给这个 Promise 添加了一个 .then() 回调函数。
    这个回调函数会在 Promise 状态变为 resolved 时执行,并被放入 微任务队列中。
  3. alert("code finished");
    同步代码立即执行,显示 “code finished” 这个 alert。
  4. 当前的同步代码执行完毕后,JavaScript 引擎会检查微任务队列。
    微任务队列中有一个任务(即在前一步中添加到 Promise 的 .then() 回调函数)。
  5. 执行微任务队列中的任务,即执行 .then() 回调函数,显示 “promise done!” 。

示例2: 未处理的 rejection

每个宏任务之后,引擎会立即执行微任务队列中的所有任务,然后再执行其他的宏任务,或渲染,或进行其他任何操作。

如果一个 promise 的 error 未被在微任务队列的末尾进行处理,则会出现“未处理的 rejection”。
如果一个promise返回error,但我们忘记添加 .catch,会被unhandledrejection捕获并报错

let promise = Promise.reject(new Error("Promise Failed!"));

setTimeout(
	() => promise.catch(err => alert('caught') 
), 1000); // setTimeout 宏任务

// Error: Promise Failed!
window.addEventListener('unhandledrejection', event => alert(event.reason));

解析:

  1. let promise = Promise.reject(new Error("Promise Failed!"))
    同步代码执行,创建了一个被reject的 Promise 对象。
  2. setTimeout(回调函数, 1000)
    宏任务被触发,它会在至少 1 秒后将 回调函数 添加到微任务队列中。
  3. window.addEventListener()同步执行
    添加事件监听器,当 Promise 被拒绝且没有被捕获时,unhandledrejection 事件会作为一个宏任务被触发,显示“Promise Failed!”
  4. 所有同步代码执行完毕后,Js 引擎开始执行微任务队列中的任务。
    这时,第二行代码中的回调函数promise.catch(err => alert('caught')) 被执行,它是一个微任务(会在当前宏任务执行完成后立即执行),显示“caught”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你脸上有BUG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值