Javascript 我们是否可以有一个调度器,您可以异步添加要执行的内容,但将以该顺序同步执行?

Javascript 我们是否可以有一个调度器,您可以异步添加要执行的内容,但将以该顺序同步执行?,javascript,asynchronous,Javascript,Asynchronous,作为我的另一个问题的“分支”问题(参见编辑4) 我想知道当你有一组这样的函数时会发生什么: function convertTileToRGB(tile,whatToDoNext){ tile.img.onload = function() { //async code returns pixels whatToDoNext(pixels); } } function doSomethingWithTile(tile,params){

作为我的另一个问题的“分支”问题(参见编辑4)

我想知道当你有一组这样的函数时会发生什么:

function convertTileToRGB(tile,whatToDoNext){
    tile.img.onload = function() {
        //async code returns pixels
        whatToDoNext(pixels);
    }

}

function doSomethingWithTile(tile,params){
    convertTileToRGB(tile,function(pixels){
        //manipulate pixels in tile
    });
}

function doSomethingWithTile2(tile,params){
    convertTileToRGB(tile,function(pixels){
        //manipulate pixels in a different way
    });
}
sequence(tile, thingsToDo);
有没有一种方法可以像这样任意调用序列

var tile = initialize_tile();

doSomethingWithTile(tile,params1)
doSomethingWithTile2(tile,params2)
doSomethingWithTile(tile,params3)  
...
这是动态的,事先不知道,换句话说,在程序运行时异步添加到调度程序,然后调度程序同步调用它们,以某种方式解决

如果我们没有调度器,并且使用回调,我们可以看到这些方法分别作用于初始化的磁贴,但它们的动作不会累积到磁贴。在该示例中,顺序被保留,但基本上,上一个异步方法的结果不会在下一个异步方法中使用

提前谢谢你的帮助

编辑: 谢谢你的回答。是的,顺序很重要,但这张清单一直在改变(添加了更多的东西),而且事先还不知道。如果有一种方法可以让一个dispatcher对象异步添加按特定顺序要执行的操作,但它将以该顺序同步调用它们,那就太好了。我相应地改变了我的问题,因为大多数人都感到困惑

EDIT2: 正在尝试更改我的代码: 调度程序如下所示。每个调用的tile和sample可能不同,但对于某些调用可能相同。将应用除addSample之外的其他操作。如果使用相同的磁贴,则调用更改应按该顺序累积在磁贴中。最重要的是,调度器应该能够异步执行更多操作

var sample = [[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f],[0x7f,0x7f,0x7f]]
var tile = initialize_tile({width: 7,height: 7,defaultColor: [0x00,0xAA,0x00], x: 1, y: 2, zoomLevel: 1});
var dispatcher = { 
    0:{
        func: addSample, 
        tile: tile,
        sample: sample, 
        num_samples: 6, 
        which_sample: 1
    },
    1:{
        func: addSample, 
        tile: tile,
        sample: sample, 
        num_samples: 6, 
        which_sample: 2
    },
       2:{
               func: render,
               tile: tile,
         }
};
var disp = dispatcher[0];
disp.func(disp.tile,disp.sample,disp.num_samples,disp.which_sample);    
disp = dispatcher[1];
disp.func(disp.tile,disp.sample,disp.num_samples,disp.which_sample);

使用该代码,不会保留顺序,并且不会为下一次调用保留磁贴发生的情况。

如果您希望能够按照定义的顺序链接doSomething调用,唯一的方法是允许doSomething在完成时发出信号,类似于convertTileToRGB的方式:

function doSomethingWithTile(tile,params, onDone){
    convertTileToRGB(tile,function(pixels){
        //manipulate pixels in tile
        onDone();
    });
}
最后,您的代码看起来像

doSomethingWithTile(tile,params1, function(){
    doSomethingWithTile2(tile,params2, function(){
        doSomethingWithTile(tile,params3, function(){
           //...
        });
    });
});
现在,代码保证以正确的顺序运行。“末日金字塔”模式有点难看,因此您可能希望找到一种解决方法,或者使用命名函数而不是匿名函数进行回调,或者使用“sequencer”库函数:

 //There are lots of async control flow libraries available for Javascript.
 // All of them should allow you to write code sort of like this one:
sequencer([
    function(onDone){ doSomethingWithTile(tile,params1, onDone) },
    function(onDone){ doSomethingWithTile(tile,params2, onDone) },
    function(onDone){ doSomethingWithTile(tile,params3, onDone) }
], function(){
    //...
});
您还可以更动态地执行操作:

function render_stuff(argss, onDone){

    var i = 0;
    function loop(){
        if(i < argss.length){
            var args = argss[i];
            addSample(args.tile, args.sample, args.num_samples, args.which_sample, function(){
               i = i + 1;
               loop();
            });
        }else{
            render(tile, onDone);
        }
    }

    loop();
}

render_stuff([
   {tile:tile, sample:sample, num_samples:6, which_sample:1},
   {tile:tile, sample:sample, num_samples:6, which_sample:2}
], function(){
    console.log("done rendering");
 });
function render_stuff(argss,onDone){
var i=0;
函数循环(){
如果(i<参数长度){
var args=argss[i];
addSample(args.tile,args.sample,args.num_samples,args.which_sample,function()){
i=i+1;
loop();
});
}否则{
粉刷(瓷砖、onDone);
}
}
loop();
}
渲染([
{tile:tile,sample:sample,num_samples:6,其中_sample:1},
{tile:tile,sample:sample,num_samples:6,哪个_sample:2}
],函数(){
console.log(“完成渲染”);
});
如果这些函数不是异步的,这将相当于一些类似于

function render_stuff(argss){
    i = 0;
    while(i < argss.length){
      var args = argss[i];
      addSample(/**/);
      i = i + 1;
    }
    render(tile);
}

render_stuff([
    {/*...*/}, 
    {/*...*/}
])
console.log("done rendering");
function render_stuff(argss){
i=0;
而(i
如果您希望能够以定义的顺序链接doSomething调用,唯一的方法是允许doSomething在完成时发出信号,类似于convertTileToRGB的方式:

function doSomethingWithTile(tile,params, onDone){
    convertTileToRGB(tile,function(pixels){
        //manipulate pixels in tile
        onDone();
    });
}
最后,您的代码看起来像

doSomethingWithTile(tile,params1, function(){
    doSomethingWithTile2(tile,params2, function(){
        doSomethingWithTile(tile,params3, function(){
           //...
        });
    });
});
现在,代码保证以正确的顺序运行。“末日金字塔”模式有点难看,因此您可能希望找到一种解决方法,或者使用命名函数而不是匿名函数进行回调,或者使用“sequencer”库函数:

 //There are lots of async control flow libraries available for Javascript.
 // All of them should allow you to write code sort of like this one:
sequencer([
    function(onDone){ doSomethingWithTile(tile,params1, onDone) },
    function(onDone){ doSomethingWithTile(tile,params2, onDone) },
    function(onDone){ doSomethingWithTile(tile,params3, onDone) }
], function(){
    //...
});
您还可以更动态地执行操作:

function render_stuff(argss, onDone){

    var i = 0;
    function loop(){
        if(i < argss.length){
            var args = argss[i];
            addSample(args.tile, args.sample, args.num_samples, args.which_sample, function(){
               i = i + 1;
               loop();
            });
        }else{
            render(tile, onDone);
        }
    }

    loop();
}

render_stuff([
   {tile:tile, sample:sample, num_samples:6, which_sample:1},
   {tile:tile, sample:sample, num_samples:6, which_sample:2}
], function(){
    console.log("done rendering");
 });
function render_stuff(argss,onDone){
var i=0;
函数循环(){
如果(i<参数长度){
var args=argss[i];
addSample(args.tile,args.sample,args.num_samples,args.which_sample,function()){
i=i+1;
loop();
});
}否则{
粉刷(瓷砖、onDone);
}
}
loop();
}
渲染([
{tile:tile,sample:sample,num_samples:6,其中_sample:1},
{tile:tile,sample:sample,num_samples:6,哪个_sample:2}
],函数(){
console.log(“完成渲染”);
});
如果这些函数不是异步的,这将相当于一些类似于

function render_stuff(argss){
    i = 0;
    while(i < argss.length){
      var args = argss[i];
      addSample(/**/);
      i = i + 1;
    }
    render(tile);
}

render_stuff([
    {/*...*/}, 
    {/*...*/}
])
console.log("done rendering");
function render_stuff(argss){
i=0;
而(i
问题在于,在每次操作发生之前,对
convertTileToRGB
的所有调用都开始对tile的引用进行操作

如果希望操作是加法的,则必须使每个操作对前一个操作的结果起作用,但要使其起作用,必须等待前一个操作结束

我不知道您实际上正在执行哪些操作,但也可以以“增量”非破坏性方式执行这些操作


如果这不是一个选项,为了控制包含代码可读性的一系列回调,我建议使用一些流控制库,如

问题是,在每次操作发生之前,对
convertTileToRGB
的所有调用都开始作用于对tile的引用

如果希望操作是加法的,则必须使每个操作对前一个操作的结果起作用,但要使其起作用,必须等待前一个操作结束

我不知道您实际上正在执行哪些操作,但也可以以“增量”非破坏性方式执行这些操作

如果这不是一个选项
dispatcher.addNew({func: addSample, config: {tile: tile,sample: sample, num_samples: 6, which_sample: 1}});
dispatcher.addNew({func: render,config: {tile: tile}});
dispatcher.addNew({func: addSample, config: {tile: tile,sample: sample2, num_samples: 6, which_sample: 2}});
dispatcher.addNew({func: render,config: {tile: tile}});
dispatcher.addNew({func: addSample, config: {tile: tile,sample: sample3, num_samples: 6, which_sample: 3}});
dispatcher.addNew({func: render,config: {tile: tile}});
dispatcher.addNew({func: addSample, config: {tile: tile,sample: sample4, num_samples: 6, which_sample: 4}});
dispatcher.addNew({func: render,config: {tile: tile}});
dispatcher.addNew({func: addSample, config: {tile: tile,sample: sample5, num_samples: 6, which_sample: 5}});
setInterval(function(){dispatcher.check();},1000);