Javascript implementation order of grammar (full version)

First we look at such a demand:

There is such a set of operations: pre, a1, a2, a3, b1, b2, b3, suf, each operation takes a long time of uncertainty, which may need to access the network or wait for incident response, in short, I need to pass a callback function then let it be fun when to call.

Suppose we need are: A and B can only be executed after completion of pre callback, and A and B each need to ensure the implementation of the order, and between A and B is no need to consider the order. After completion of the implementation of A and B must be performed suf. ES5 with callback function to achieve it is undoubtedly a cause for the collapse of thing.

Now look at how I do:

new syn(function*(method){
	console.log('syn in');
	let pre = yield method.exc(callback, "pre", this);
	console.log(pre);

	method.syn(function*(m){
		yield m.exc(callback, "a1", this);
		yield m.exc(callback, "a2", this);
		yield m.exc(callback, "a3", this);
		return "你开心就好";
	});
	method.syn(function*(m){
		let [w1] = yield m.exc(callback, "b1", this);
		let w2 = yield m.exc(callback, "b2", this);
		let w3 = (yield m.exc(callback, "b3", this))[0];
		return w1+w2[0]+w3;
	});
	method.syn(function*(m){
		m.exc(callback, "c1", this);
		m.exc(callback, "c2", this);
		m.exc(callback, "c3", this);
		return yield m.muti();
	});
	let [A, B, C] = yield method.muti();
	console.log(A);
	console.log(B);
	console.log(C);

	method.exc(callback, "suf1", this);
	method.exc(callback, "suf2", this);
	let [suf1, suf2] = yield method.muti();
	console.log(suf1);
	console.log(suf2);
	console.log("syn out");
});

function callback(name, func) {
	console.log("执行函数:"+name);
	setTimeout(func, Math.ceil(Math.random()*2)*1000, "函数回调:"+name);
}

In the above example, I use the data A, B, C of the three groups of parallel processing, in order to more clearly the function execution process performance:

In the above example, when the pre finished, for a1, b1, c1 successive calls, wherein the A, B requires only to initiate a call to the outcome of the next call, C is simultaneously called to wait for all results returned together.

In syn block, only when a yield after obtaining expression results, the following code will be able to run

Syn actually implements the principle is very simple, just use syntactic sugar for ES6, its essence is still nested callback function, and does not open a new thread. But using syn block code readability tragically huge boost.

The following is a specific code syn method:

function syn(func, onreturn=null) {
	let method = {};
	let it = func.call(func, method);

	let ly;
	let results;
	let count = 0;
	let callback = (index,result) =>{
		count--;
		if(ly.value) {
			results[index] = result;
			if(!count) {
				ly = it.next(results);
			}
		} else {
			ly = it.next(result);
		}
		if(onreturn&&ly.done) {
			//console.log(ly.done);
			onreturn(ly.value);
		}
	};
	
	// 返回之前请求的全部值
	method.muti = ()=>{results = new Array(count);return true;};

	// 特别的,如果对多路并发请求需要进行并行处理的,可以调用syn方法‘开启子线程’
	// syn方法应当配合muti使用
	method.syn = (fun)=>{
		let index = count++;
		new syn(fun, (v)=>{
			callback(index, v);
		});
		return false;
	};
	// 执行外部方法,此处必须使用function,不能使用箭头函数,否则arguments无法获取外部传入的参数
	method.exc = function(){
		let index = count++;
		let target = arguments[0];
		let args = [];
		for(let i=1; i<arguments.length; i++) {
			if(func==arguments[i]) {
				args.push(function(){
					callback(index, arguments);
				});
			} else {
				args.push(arguments[i]);
			}
		}
		target.apply(func, args);
		return false;
	};
	// 扩展
	method.next = (v)=>it.next(v);

	ly = it.next();
};

 

Published 11 original articles · won praise 8 · views 8853

Guess you like

Origin blog.csdn.net/qq_26946497/article/details/85055046