neo-async 模块

简介: 通过 promise 控制并发数量

neo-async 和 async 模块都是为了解决嵌套金字塔,和异步流程控制而生,neo-async 是 async 的替代品,因为 neo-async 比 async 的性能更快。

为什么要使用这个模块,举个例子,比如我们需要读取多个文件,将读取文件的结果保存在数组中。

let list = []
fs.readFile('file1', 'utf8', function (err, res) {
  list.push(res)
  fs.readFile('file2', 'utf8', function (err, res) {
    list.push(res)
    fs.readFile('file3', 'utf8', function (err, res) {
      list.push(res)
      console.log(res)
    })
  })
})

使用 neo-async 我们可以这样写:

function getFile(file, callback) {
  fs.readFile(file, 'utf8', function (err, res) {
    if (err) {
      return callback(err);
    }
    callback(null, res);
  });
}

async.map(['file1','file2','file3'], getFile, function(err, results) {
    // 返回一个新数组
    console.log(res)
});

each

注意,由于此函数并行地将 iterator 应用于每个项,因此不能保证 iterator 函数将按顺序完成。
// array
var order = [];
var array = [1, 3, 2];
var iterator = function(num, done) {
  setTimeout(function() {
    order.push(num);
    done();
  }, num * 10);
};
async.each(array, iterator, function(err, res) {
  console.log(res); // undefined
  console.log(order); // [1, 2, 3]
});
与 each 相同,但一次最多运行多少异步操作,可以自己设置限制。

eachLimit

// array
var order = [];
var array = [1, 5, 3, 4, 2];
var iterator = function(num, done) {
  setTimeout(function() {
    order.push(num);
    done();
  }, num * 10);
};
async.eachLimit(array, 2, iterator, function(err, res) {
  console.log(res); // undefined
  console.log(order); // [1, 3, 5, 2, 4]
});

控制并发数量的实现原理如下:

var noop = function noop() {};

function timesSync(n, iterator) {
  var index = -1;
  while (++index < n) {
    iterator(index);
  }
}
function eachLimit(collection, limit, iterator, callback) {
  callback = callback || noop;
  var size = collection.length;
  var sync = false;
  var started = 0;
  var completed = 0;

  timesSync(limit > size ? size : limit, iterate);

  function iterate() {
    if (started < size) {
      iterator(collection[started++], done);
    }
  }

  function done(err, bool) {
    if (err) {
      callback(err);
    } else if (++completed === size) {
      callback(null);
    } else {
      iterate();
    }
  }
}

我们都知道异步编程的方式有很多种,包括回调和 promise 的形式,下面是通过 promise 控制并发数量。

/**
 * @params list {Array} - 要迭代的数组
 * @params limit {Number} - 并发数量控制数
 * @params asyncHandle {Function} - 对`list`的每一个项的处理函数,参数为当前处理项,必须 return 一个Promise来确定是否继续进行迭代
 * @return {Promise} - 返回一个 Promise 值来确认所有数据是否迭代完成
 */
let eachLimit = (list, limit, asyncHandle) => {
  let recursion = (arr) => {
    return asyncHandle(arr.shift()).then((res) => {
      // console.log(res)
      if (arr.length !== 0) {
        return recursion(arr) // 数组还未迭代完,递归继续进行迭代
      }
    })
  };

  let listCopy = [].concat(list);
  let asyncList = []; // 正在进行的所有并发异步操作
  while (limit--) {
    asyncList.push(recursion(listCopy));
  }
  return Promise.all(asyncList);  // 所有并发异步操作都完成后,本次并发控制迭代完成
}

const order = []
const timeout = i => new Promise(resolve => {
  setTimeout(() => {
    order.push(i)
    resolve(i)
  }, i * 10)
});
eachLimit([1, 5, 3, 4, 2], 2, timeout).then((res) => {
  console.log(order)
})
相关文章
|
3月前
|
JavaScript 前端开发
Hooks使用createStore、Provider、useSelector、useDispatch实现connect功能
使用React Hooks实现connect功能,通过createStore创建仓库,Provider提供store,useSelector获取state,useDispatch触发action,从而在函数式组件中管理状态,替代类组件中的connect功能。
38 5
Hooks使用createStore、Provider、useSelector、useDispatch实现connect功能
|
5月前
|
存储 JavaScript 安全
Node中的AsyncLocalStorage 使用问题之nestjs-cls 库提供了什么功能
Node中的AsyncLocalStorage 使用问题之nestjs-cls 库提供了什么功能
|
6月前
|
存储 前端开发 安全
Nuxt3 实战 (十):使用 Supabase 实现 RESTful 风格 API 接口
这篇文章介绍了如何使用Supabase实现RESTful风格的API接口,用于网站分类和子站点的增删改查(CURD)功能。文章首先阐述了表设计,包括ds_categorys和ds_websites两张表的列名、类型和用途,并提到了为每张表添加的user_id和email字段以支持用户身份识别。接着,文章描述了接口设计,以ds_websites表为例,说明了如何通过RESTful API实现CURD功能,并给出了使用SupabaseClient实现插入数据的相关代码。文章最后提供了项目效果预览和总结,指出学习了Nuxt3创建接口及调用Supabase数据库操作。
115 2
Nuxt3 实战 (十):使用 Supabase 实现 RESTful 风格 API 接口
|
IDE Go 开发工具
GO模块引入指令Go Mod
GO模块引入指令Go Mod
138 7
|
7月前
|
Go
Go 封装 mongo
Go 封装 mongo
65 0
nodejs path.resolve与path.join如何使用
nodejs path.resolve与path.join如何使用
|
JavaScript
Pure Admin框架学习笔记---1 (认识它)
Pure Admin框架学习笔记---1 (认识它)
590 0
go原生log模块的简易封装
go原生log模块的简易封装
|
前端开发 JavaScript
nodejs fs模块结合async await处理fs异步使用
nodejs fs模块结合async await处理fs异步使用
135 0
nodejs fs模块结合async await处理fs异步使用