zoukankan      html  css  js  c++  java
  • nodejs 同步执行异步函数

    有时候要运行某个异步方法, 但不能对它重写为同步的时候, 就需要此函数进行处理.

    实现方式目前有两个, 一和是使用 c++ 编译处理, 一种是使用 exec .

    如果编译则需要安装一系列相关的依赖, 比较麻烦, 对于简单使用时, 推荐使用 exec.

    在开发 mockm(一款感觉简单而强大的前后端接口联调工具) 时, 使用到的一个工具库就引用了一个叫 promise-synchronizer 的库来进行同步运行异步方法, 感觉用户安装起来十分麻烦.

    promise-synchronizer 依赖了 deasync 库, 这个库需要使用 python 2 编译. 如果使用者的电脑上没有 python 2 则安装出错, 如果客户使用 node14+ 则安装出错, 因为 node14+ 使用了 python 3.

    所以我便对工具进行了重写, 以下为简单实现的代码和示例:

    function asyncTosync(fn) { // 同步执行异步函数, 入参和出参需要可序列化, 不会输出出参数之外的其他信息
      return (...args) => {
        const { writeFileSync, readFileSync } = require(`fs`)
        const fnStr = fn.toString()
        const tempDir = require(`os`).tmpdir().replace(/\/g, `/`)
        const fileObj = {
          fnFile: `${tempDir}/fnFile_${Date.now()}.js`,
          resFile: `${tempDir}/resFile_${Date.now()}.json`,
          errFile: `${tempDir}/errFile_${Date.now()}.json`,
        }
        writeFileSync(fileObj.fnFile, ``, `utf8`)
        writeFileSync(fileObj.resFile, ``, `utf8`)
        writeFileSync(fileObj.errFile, ``, `utf8`)
        const argsString = args.map(arg => JSON.stringify(arg)).join(', ');
        const codeString = `
          const { writeFileSync } = require('fs')
          const fn = ${fnStr}
          new Promise(() => {
            fn(${argsString})
              .then((output = '') => {
                writeFileSync("${fileObj.resFile}", output, 'utf8')
              })
              .catch((error = '') => {
                writeFileSync("${fileObj.errFile}", error, 'utf8')
              })
            }
          )
        `
        writeFileSync(fileObj.fnFile, codeString, `utf8`)
        console.log(`fileObj`, fileObj)
        require(`child_process`).execSync(`"${process.execPath}" ${fileObj.fnFile}`)
        const res = readFileSync(fileObj.resFile, `utf8`)
        const err = readFileSync(fileObj.errFile, `utf8`)
        return {res, err}
      }
    }
    const fn = time => new Promise((resolve, reject) => {
      setTimeout(() => resolve(`ok ${time}`), time);
    })
    
    
    const sleep = ms => new Promise(r => setTimeout(r, ms))
    console.log(`1s`)
    const {res, err} = asyncTosync(sleep)(3e3)
    console.log({res, err})
    console.log(`5s`)
    
  • 相关阅读:
    存储过程中执行动态Sql语句
    SqlServer新建视图
    DataGridView DataGridViewCheckBoxColumn编辑时实时触发事件
    oracle number 和sqlserver numeric的区别
    放下你的无效社交
    一个程序员眼中的北京和上海
    10+年程序员总结的20+条经验教训
    SQL collate
    SQL自定义函数split分隔字符串
    C# .NET开发Oracle数据库应用程序
  • 原文地址:https://www.cnblogs.com/daysme/p/14041821.html
Copyright © 2011-2022 走看看