Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

对比几个异步管理的库 #8

Open
Zaynex opened this issue Dec 16, 2020 · 0 comments
Open

对比几个异步管理的库 #8

Zaynex opened this issue Dec 16, 2020 · 0 comments

Comments

@Zaynex
Copy link
Owner

Zaynex commented Dec 16, 2020

p-map

Usage

const pMap = require('p-map');
const got = require('got');

const sites = [
	getWebsiteFromUsername('https://sindresorhus'), //=> Promise
	'https://ava.li',
	'https://github.com'
];

(async () => {
	const mapper = async site => {
		const {requestUrl} = await got.head(site);
		return requestUrl;
	};

 	const result = await pMap(sites, mapper, {concurrency: 2});

	console.log(result);
	//=> ['https://sindresorhus.com/', 'https://ava.li/', 'https://github.com/']
})();

简析

在接口设计上,第一个传递的是资源列表,第二个参数是执行的异步任务。第三个参数有可选项,分别是并行数量以及异常后是否继续执行。

如何实现并发

本质上先从数组取 concurrency 个资源执行,当异步资源结束后再继续执行下一个。这样可以确保每次执行都能保持稳定并发。

在其内部实现中,数组本身是一个内置可迭代对象,可以通过 [Symbol.iterator] 访问其迭代属性,该属性是一个方法,还需要进行调用()才会返回可迭代对象。


(async () => {
    try {
	    const element = await nextItem.value;
	    result[index] = await mapper(element, index);
	    resolvingCount--;
	    next();
    } catch (error) {
	    if (stopOnError) {
		    isRejected = true;
		    reject(error);
	    } else {
		    errors.push(error);
		    resolvingCount--;
		    next();
	    }
    }
    })();

外层包裹的是 promise,可以确保当某个任务异常的话及时 reject 掉。

因为用了 asyncawait 以及Smobol.iterator,兼容性是偏高的,对于 Node 项目倒是可行,前端项目的话,还不能直接用。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant