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