用于处理多个未知回调的Javascript函数 [英] Javascript function for handling multiple unknown callbacks
问题描述
我有一种情况,我想将2个或更多函数(作为参数)发送到处理程序函数中,并让该处理程序函数将每个传递的函数作为上一个函数的回调函数执行。
这是我要编写的函数的一般概念:
function functionChain (){
//确保我们至少有1个参数
if(arguments.length< 1){return; }
//对于每个参数,将其称为(作为函数)
for(var i = 0; i< arguments.length; i ++){
if(typeof arguments [i] ==='function'){
调用参数[i];
}
}
}
//示例
functionChain(function1,function2,function3);
...因此在上面的代码中,每个函数将被连续调用。
我遇到的麻烦是,在上一个函数完成后,如何将每个调用视为回调。
我的方式方法是拥有一个变量(为简单起见,只说一个名为functionChainComplete的全局变量),然后等待启动下一个函数-当然,我调用的每个函数都会将functionChainComplete设置为true。因此,是这样的:
//设置全局变量来跟踪
var functionChainComplete;
function functionChain(){
//确保我们至少有1个参数
if(arguments.length< 1){return; }
//将全局变量设置为FALSE
functionChainComplete = true;
//为每个参数调用(作为函数)
for(var i = 0; i< arguments.length; i ++){
if(typeof arguments [ i] ==='function'){
if(functionChainComplete == true){
//调用下一个函数,然后再次等待true
functionChainComplete = false;
个调用参数[i];
}否则{
//在50毫秒后重试(也许是setTimeout)?
}
}
}
}
function1(){
//进行某些操作,完成后重置functionChainComplete
functionChainComplete = true;
}
function2(){
//做点什么,完成后,重置functionChainComplete
functionChainComplete = true;
}
function3(){
//做点事情,完成后,重置functionChainComplete
functionChainComplete = true;
}
//示例
functionChain(function1,function2,function3);
如您所见,上面的代码没有解决回调部分,而且我不确定在哪里从这里开始-我怀疑某种递归函数?我被困住了。
假设您有一些功能, double
,需要一个参数 x
和一个回调 k
const double =(x,k)=> k(x * 2)double(2,console.log)// 4double(3,console.log)// 6
现在说我们要连续运行3次
const double =(x,k)=> k(x * 2)const TripleDouble =(x,k)=> double(x,y => double(y,z => double(z,k)))TripleDouble(2,console.log)// 16tripleDouble(3,console.log)// 24
但是我们当然必须静态地编码每个延续( y => ...
和 z => ...
)。我们如何使用可变数量(数组)的函数来完成这项工作?
const double =(x,k)=> k(x * 2)const composek =(... fs)=> (x,k)=> fs.reduce((acc,f)=> k => acc(x => f(x,k)),k => k(x))(k)const foo = composek(double,double ,double)foo(2,console.log)// 16foo(3,console.log)// 24
对于某些抽象来说已经成熟,并介绍了我最喜欢的单子,即Continuation Monad。
const Cont = f => ({{runCont:f,chain:g => Cont(k => f(x => g(x).runCont(k)))})Cont.of = x => Cont(k => k(x))const composek =(... fs)=> (x,k)=> fs.reduce((acc,f)=> acc.chain(x => Cont(k => f(x,k))),Cont.of(x))。runCont(k)const double = (x,k)=> k(x * 2)const foo = composek(double,double,double)foo(2,console.log)// 16foo(3,console.log)// 24
如果您可以自由更改要链接的功能,则可以清除更多内容–在这里, double
有1个参数并返回 Cont
而不是将回调作为第二个参数
const Cont = f => ({{runCont:f,chain:g => Cont(k => f(x => g(x).runCont(k)))})Cont.of = x => Cont(k => k(x))//简化的const composek =(... fs)=> (x,k)=> fs.reduce((acc,f)=> acc.chain(f),Cont.of(x))。runCont(k)//简化的const double = x => Cont.of(x * 2)const foo = composek(double,double,double)foo(2,console.log)// 16foo(3,console.log)// 24
当然,如果 double
实际上是异步的,它将
//将double更改为异步;输出保持不变
const double = x =>
Cont(k => setTimeout(k,1000,x * 2))
const foo = composek(double,double,double)
foo( 2,console.log)// 16
foo(3,console.log)// 24
I have a scenario where I would like to send in 2 or more functions (as parameters) into a handler function, and have that handler function execute each passed function as a callback function for the preceding function.
Here is a general concept of the function I am trying to write:
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) { return; }
// for each parameter, call it (as a function)
for ( var i=0; i<arguments.length; i++) {
if ( typeof arguments[i] === 'function' ) {
call arguments[i];
}
}
}
// example
functionChain( function1, function2, function3 );
... so in the code above, each function will be called in succession.
Where I am getting stuck is how to treat each call as a callback when the previous function completes.
The way I would approach this is to have a variable (for simplicity, lets just say a global variable named functionChainComplete), and wait to launch the next function -- and of course, each function I call would set functionChainComplete to true. So, something like this:
// set global var for tracking
var functionChainComplete;
function functionChain() {
// MAKE SURE WE HAVE AT LEAST 1 PARAMETER
if ( arguments.length < 1 ) { return; }
// SET GLOBAL VAR TO FALSE
functionChainComplete = true;
// for each parameter, call it (as a function)
for ( var i=0; i<arguments.length; i++) {
if ( typeof arguments[i] === 'function' ) {
if ( functionChainComplete == true ) {
// call the next function and wait for true again
functionChainComplete = false;
call arguments[i];
} else {
// try again in 50 ms (maybe setTimeout)?
}
}
}
}
function1() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
function2() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
function3() {
// do something, and when done, reset functionChainComplete
functionChainComplete = true;
}
// example
functionChain( function1, function2, function3 );
As you can see, the code above does not address the callback piece, and I am not sure where to take it from here - I suspect some sort of recursive function? I am stuck.
Say you have some function, double
, that takes an argument, x
, and a callback, k
const double = (x, k) =>
k(x * 2)
double(2, console.log) // 4
double(3, console.log) // 6
Now say we want to run it 3 times in a row
const double = (x, k) =>
k(x * 2)
const tripleDouble = (x, k) =>
double(x, y =>
double(y, z =>
double(z, k)))
tripleDouble(2, console.log) // 16
tripleDouble(3, console.log) // 24
But of course we had to statically code each continuation (y => ...
, and z => ...
). How would we make this work with a variable amount (array) of functions?
const double = (x, k) =>
k(x * 2)
const composek = (...fs) => (x, k) =>
fs.reduce((acc, f) =>
k => acc(x => f(x, k)), k => k(x)) (k)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
This is ripe for some abstraction tho, and introduces my favourite monad, the Continuation Monad.
const Cont = f => ({
runCont: f,
chain: g =>
Cont(k => f(x => g(x).runCont(k)))
})
Cont.of = x => Cont(k => k(x))
const composek = (...fs) => (x, k) =>
fs.reduce((acc,f) =>
acc.chain(x =>
Cont(k => f(x,k))), Cont.of(x)).runCont(k)
const double = (x, k) =>
k(x * 2)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
If you have freedom to change the functions you're chaining, this cleans up a little bit more – here, double
has 1 parameter and returns a Cont
instead of taking a callback as a second argument
const Cont = f => ({
runCont: f,
chain: g =>
Cont(k => f(x => g(x).runCont(k)))
})
Cont.of = x => Cont(k => k(x))
// simplified
const composek = (...fs) => (x, k) =>
fs.reduce((acc,f) => acc.chain(f), Cont.of(x)).runCont(k)
// simplified
const double = x =>
Cont.of(x * 2)
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
Of course if double
was actually asynchronous, it would work the same
// change double to be async; output stays the same
const double = x =>
Cont(k => setTimeout(k, 1000, x * 2))
const foo = composek(double, double, double)
foo(2, console.log) // 16
foo(3, console.log) // 24
这篇关于用于处理多个未知回调的Javascript函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!