合并请求之promise闭包

import React from 'mui/reactjs/react';
import Callbacks from './callbacks';
import Request from './request';

const PAGE_PREFIX = 'ostium';
const API_PREFIX = 'api';

const cache = {};

const convertPermission = (keys, type = API_PREFIX)=> {
	const apis = keys.split(',');
	return apis.map(api => {
		api = api.trim();
		if (api) {
			return [type].concat(api.split('/')).join('-');
		}
	}).filter(api=>!!api);
};

const getPermissions = apis => Promise.all(apis.map(api => new Promise((resolve) => {
	if (!cache[api]) {
		cache[api] = Callbacks();
		Request(api).then(cache[api].fire).catch(() => {
			// 请求失败后,先标记为无权限,再清空缓存,下次可以重试
			cache[api].fire(false);
			delete cache[api];
		});
	}
	cache[api].add(result => {
		const obj = {};
		obj[api] = result;
		resolve(obj);
	});
}))).then(results => results.reduce((prev, current)=> Object.assign(prev, current), {}));

class Component extends React.Component {
	constructor(props) {
		super(props);
		this.init = this.init.bind(this);
		this.state = {
			authorized: false
		};
	}

	componentDidMount() {
		this.init(this.props);
	}

	componentWillReceiveProps(next) {
		if (!next.apiKeys || !next.pageKeys) {
			return;
		}
		if (next.apiKeys !== this.apiKeys || next.pageKeys !== this.pageKeys) {
			this.init(next);
		}
	}

	init(props) {
		const {apiKeys, pageKeys} = props;
		let permissions;
		if (apiKeys) {
			permissions = convertPermission(apiKeys);
		} else if (pageKeys) {
			permissions = convertPermission(pageKeys, PAGE_PREFIX);
		}
		if (permissions) {
			getPermissions(permissions).then(this.judge.bind(this)).catch(()=> {
			});
		}
	}

	judge(data) {
		this.setState({
			authorized: Object.values(data).every(v => v)
		});
	}

	static canUseApi = (apiKeys) => {
		return getPermissions(convertPermission(apiKeys)).then(data => {
			return {
				result: Object.values(data).every(v => v),
				data: data
			}
		});
	};

	static canUsePage = (pageKeys) => {
		return getPermissions(convertPermission(pageKeys, PAGE_PREFIX)).then(data=> {
			return {
				result: Object.values(data).every(v => v),
				data: data
			}
		});
	};

	render() {
		const { type='hide' } = this.props;
		let { authorized } = this.state;
		let { children } = this.props;

		if (!(children instanceof Array)) {
			children = [children];
		}
		return (
			<span style={this.props.style} className={this.props.className}>
			{
				authorized ? children :
					type == 'hide' ? '' :
						type == 'disabled' ?
							children.map(o => {
								return React.cloneElement(o, {disabled: true})
							}) :
							type == 'deny' ?
								children.map(o => {
									return React.cloneElement(o, {
										onClick: ()=> {
											o.props.onDeny && o.props.onDeny()
										}
									})
								}) : ''
			}
		</span>
		);
	}

}


// 每使用一次都要初始化。
export default Component;

Requese.js:

'use strict';
const fetch = require('ascm-comp/lib-fetch/index');

module.exports = (()=> {
	const cache = {};
	const host = (window._env_ === 'pre' || window._env_ == 'prod') ? 'xx' : 'yy';
	const url = `//${host}/webapi/permission/queryPermissions`;

	const request = (keys)=> {
		return new Promise((resolve, reject)=> {
			fetch({
				url,
				method: 'get',
				timeout: 1000 * 10,
				data: {
					_0: keys
				}
			}).then(res => {
				if (res.success && res.data) {
					resolve(res.data);
				} else {
					reject();
				}
			}).catch(()=> {
				reject();
			});
		})
	};

	const waitThenSend = (()=> {
		const map = {};
		const queue = [];
		let timer;

		const send = (list)=> {
			request(list).then((data)=> {
				Object.keys(data).forEach((key)=> {
					if (map[key] && map[key].resolve) {
						map[key].resolve(data[key]);
					}
				});
			}).catch(()=> {
				list.forEach((key)=> {
					if (map[key] && map[key].reject) {
						map[key].reject();
					}
					delete map[key];
					delete cache[key];
				});
			});
		};

		return (key, resolve, reject)=> {
			queue.push(key);
			map[key] = {
				resolve,
				reject
			};
			clearTimeout(timer);
			if (queue.length < 8) {
				timer = setTimeout(()=> {
					send(queue.splice(0, 8));
				}, 200);
			}
			else {
				send(queue.splice(0, 8));
			}
		};
	})();

	return key=> {
		if (!cache[key]) {
			cache[key] = new Promise((resolve, reject)=> {
				waitThenSend(key, resolve, reject);
			});
		}
		return cache[key];
	}
})();

Callbacks:

'use strict';

module.exports = ()=> {
	const queue = [];
	let fired = false;
	let result;
	return {
		add: callback=> {
			if (fired) {
				setTimeout(()=> {
					callback(result);
				}, 1);
			}
			else {
				queue.push(callback);
			}
		},
		fire: value => {
			fired = true;
			result = value;
			let t = queue.shift();
			while (t) {
				t(result);
				t = queue.shift();
			}
		}
	}
};

 

 

转载于:https://my.oschina.net/u/867090/blog/902227

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
闭包JavaScript中一个重要且强大的概念。它指的是函数能够访问自己定义范围之外的变量,并且这些变量在函数执行完毕后仍然可以被访问到。闭包的应用场景很广泛,它可以用来创建私有变量、实现模块化、延迟执行等等。了解和掌握闭包对于理解JavaScript语言的本质,以及提高代码的可维护性和灵活性都非常有帮助。 从技术的角度来看,所有的JavaScript函数都可以被看作是闭包。因为在函数内部,它们可以访问在函数定义范围之外的变量。这也是为什么在JavaScript中,函数可以在定义之后仍然可以访问外部的变量。 总结起来,闭包JavaScript中一个非常重要的概念,它能够让函数访问自己定义范围之外的变量,并且这些变量在函数执行完毕后仍然可以被访问到。了解闭包可以帮助我们更好地理解JavaScript语言的本质,并且提高代码的可维护性和灵活性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [深入理解JavaScript闭包](https://blog.csdn.net/qq_54384868/article/details/130182961)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [JavaScript深入之闭包](https://blog.csdn.net/TZOF_/article/details/117048674)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值