• JavaScript 异步函数的 Promisification 处理


    Promisification 是一个很长的词,表示一个编程范式的转变,即将接受回调的函数转换为一个返回类型为 Promise 的函数。

    我们现实的开发项目中经常需要这种转换,因为许多函数和库都是基于回调的,但是 Promise 更方便,所以对它们进行 Promisification 处理是有意义的。

    下面是一个简单的例子。

    function loadScript(src, callback) {
      let script = document.createElement('script');
      script.src = src;
    
      script.onload = () => callback(null, script);
      script.onerror = () => callback(new Error(`Script load error for ${src}`));
    
      document.head.append(script);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这段代码,动态创建一个 script 元素,待其加载完毕后,会触发 onload 事件指定的回调函数。

    运行时,loadScript 的调用者,负责指定回调函数:

    loadScript('path/script.js', (err, script) => {...})
    
    • 1

    下面我们将会对这个函数进行 Promisification 改造。

    我们将创建一个新函数 loadScriptPromise(src),它执行相同的操作(加载脚本),但返回一个 Promise 而不是使用回调。

    换句话说,我们只传递 src (没有回调)并得到一个 Promise 作为返回参数,当加载成功时使用创建并加载好的 script 进行 resolve,否则通过 reject 抛出错误。

    改造后的函数:

    let loadScriptPromise = function(src) {
      return new Promise((resolve, reject) => {
        loadScript(src, (err, script) => {
          if (err) reject(err);
          else resolve(script);
        });
      });
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    消费代码:

    loadScriptPromise('path/script.js').then(...)
    
    • 1

    正如我们所见,新函数是原始 loadScript 函数的包装器。

    在实践中,我们可能需要 Promisify 多个函数,所以构造一个 helper 函数显得更有意义。

    我们称这个函数为 promisify(f):它接受一个准备被改造成 Promise 的函数 f, 并返回一个 wrapper 函数。

    完整实现如下:

    function promisify(f) {
      return function (...args) { // return a wrapper-function (*)
        return new Promise((resolve, reject) => {
          function callback(err, result) { // our custom callback for f (**)
            if (err) {
              reject(err);
            } else {
              resolve(result);
            }
          }
    
          args.push(callback); // append our custom callback to the end of f arguments
    
          f.call(this, ...args); // call the original function
        });
      };
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    消费代码:

    let loadScriptPromise = promisify(loadScript);
    loadScriptPromise(...).then(...);
    
    • 1
    • 2
  • 相关阅读:
    php 根据经纬度查询距离
    【全志T113-S3_100ask】12-2 Linux蓝牙通信实战(BLE初窥)
    【小月电子】XILINX FPGA开发板(XLOGIC_V1)系统学习教程-LESSON8 LCD1602液晶显示
    典型相关分析CCA计算过程
    【kubernetes】kubernetes中的Controller
    python爬虫之JS逆向
    【共读】企业信息安全建设与运维指南(二)
    kkfile配置https预览文件
    3 .NET Core笔试题
    深度学习---三好学生各成绩所占权重问题(3)
  • 原文地址:https://blog.csdn.net/i042416/article/details/126335741