美文网首页
Node实现异步过程的状态同步

Node实现异步过程的状态同步

作者: 平仄_pingze | 来源:发表于2018-03-01 13:43 被阅读13次

说明

有时会遇到一个耗时异步过程(如转码、慢查询)可能被快速反复调用的情况。如果希望每次调用都能正确返回,而又不希望过程被重复执行消耗资源,可以使用下面的装饰器函数来包装过程。
注意,装饰器可以配置最大同步过程及等待时间,以有限增加和确保回收监听器,使用时应根据情况处理。

装饰器函数:

/**
  * 异步过程(函数)状态同步
  * @param asyncFunc 过程函数
  * @param opts
  *   opts.maxProcess 最大同步过程数
  *   opts.timeout 最大同步等待时间
*/
function stateSynchronize(asyncFunc, opts) {
  opts = opts || {};
  opts.maxProcess = opts.maxProcess || 100;
  opts.timeout = opts.timeout || 60 * 1000;
  const keySet = new Set();
  const emitter = new (require('events').EventEmitter)();
  emitter.setMaxListeners(opts.maxProcess);
  return async function (key, ...args) {
    if (keySet.has(key)) {
      return await (() => {
        return new Promise((resolve, reject) => {
          if (emitter.listeners('finish').length >= opts.maxProcess) {
            return reject(new Error('too much process at the same time'));
          }
          setTimeout(() => {
            return reject(new Error('process wait synchronization timeout'));
          }, opts.timeout);
          emitter.once('finish', ({key, ret}) => {
            return resolve(ret);
          });  
        });
      })();
    }
    keySet.add(key);
    let ret = await asyncFunc(...args);
    keySet.delete(key);
    emitter.emit('finish', {key, ret});
    return ret;
  }
}

测试

// 异步过程
async function work(key) {
  await (function () {return new Promise(resolve => setTimeout(() => resolve(), 2000))})();
  return key;
}

// 装饰
work = stateSynchronize(work);

// 执行
~async function() {
  process.nextTick(async () => {
    let key = 1;
    let ret = await work(key, [key]);
    console.log('1过程执行完毕,返回', ret);
  });

  setTimeout(async () => {
    for (let i=0; i< 11; i++) {
      process.nextTick(async () => {
        let key = 1;
        let ret = await work(key, [key]);
        console.log('2过程执行完毕,返回', ret);
      });
    }
  }, 1000);

  setTimeout(async () => {
    process.nextTick(async () => {
      let key = 2;
      let ret = await work(key, [key]);
      console.log('3过程执行完毕,返回', ret);
    });
  }, 1000);
}();

// 结果中,2过程和1过程有同样的key,虽然2过程执行晚了1s,但仍会和1一起结束,同样返回。

相关文章

  • Node实现异步过程的状态同步

    说明 有时会遇到一个耗时异步过程(如转码、慢查询)可能被快速反复调用的情况。如果希望每次调用都能正确返回,而又不希...

  • node教程--回调函数

    node异步读取文件: node同步读取文件: 在 Node.js 中,异步式 I/O 是通过回调函数来实现的 f...

  • 【Node.js】读取文件

    在node.js里,读取文件分为 同步读取 和 异步读取。 同步读取: fs.readFileSync() 异步读...

  • node 同步异步

    1. series(tasks,[callback]) 多个函数从上到下依次执行,相互之间没有数据交互 ...

  • 【Node.js】删除文件(基础用法)

    node.js删除文件是分为同步和异步。 同步删除文件: fs.unlinkSync() 异步删除文件: fs.u...

  • 【Node.js】写入文件

    node.js的写入文件和读取文件一样,都是分为同步和异步。 同步写入:fs.writeFileSync() 异步...

  • 【Node.js】创建文件夹(基础用法)

    node.js创建文件夹是分为同步和异步。 同步创建: fs.mkdirSync() 异步创建: fs.mkdir...

  • node.js基本模块-fs

    fs模块为node.js的内置模块,同时提供了同步和异步的方法。 简单回顾同步和异步的区别: 1.异步在执行I...

  • 04-Node 异步编程

    Node 异步编程同步方法和异步方法异步 API 的执行顺序异步编程回调地狱问题Promise 改造回调地狱代码a...

  • 三:fs模块

    node的fs模块是文件模块,为node自带的模块,负责文件的读写。fs模块可以同步和异步读写文件 1. 异步读取...

网友评论

      本文标题:Node实现异步过程的状态同步

      本文链接:https://www.haomeiwen.com/subject/diugxftx.html