1

私の他の質問からの「分岐」質問として (編集 4 を参照)キャンバス getImageData を使用せずに png base64 文字列をピクセル配列に変換する方法は?

次のような一連の関数があるとどうなるのだろうか。

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
    });
}

このような任意の呼び出しシーケンスの方法はありますか?

var tile = initialize_tile();

doSomethingWithTile(tile,params1)
doSomethingWithTile2(tile,params2)
doSomethingWithTile(tile,params3)  
...

つまり、プログラムの実行中にディスパッチャーに非同期的に追加され、ディスパッチャーがそれらを同期的に呼び出して、何らかの方法で解決する必要がありますか?

ディスパッチャーがなく、コールバックを使用する場合、メソッドは初期化されたタイルで個別に動作しますが、それらのアクションはタイルに蓄積されません。その例では順序は保持されますが、本質的に前の async メソッドの結果は次のメソッドでは使用されません。

助けてくれてありがとう

編集: 答えてくれてありがとう。はい、順序は重要ですが、このリストは常に変更されており(さらに追加されています)、事前にはわかりません。特定の順序で行われることを非同期に追加するディスパッチャ オブジェクトを用意する方法があればいいのですが、その順序で同期的に呼び出します。ほとんどの人が混乱していたので、それに応じて質問を変更しました。

EDIT2: コードを変更しようとしています: ディスパッチャーは以下のようになります。タイルとサンプルは、呼び出しごとに異なる場合がありますが、同じ場合もあります。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);

そのコードでは、順序が保持されず、タイルに何が起こったのかが次の呼び出しのために保持されません。

4

6 に答える 6

0

JavaScript Promisesを確認できます。たぶん、彼らはあなたの問題に取り組むためのいくつかの有用な方法を提供します.

于 2013-06-23T20:00:43.447 に答える
0

わかりましたので、さまざまな署名で呼び出される todo メソッドを非同期的に追加できるディスパッチャーを作成しました。実際にそれらを 1 つずつ呼び出す setInterval があります。https://stackoverflow.com/users/90511/missingnohttps://stackoverflow.com/users/182668/pointyに感謝します一連のメソッドを呼び出すというアイデアが与えられました。問題は、すべての関数を同じ署名を持つように変更し、ディスパッチャーが呼び出す必要があるかどうかを確認する cronjob を持たなければならなかったことです (Pointy にはそれがありましたが、一見しただけではわかりませんでした)。それらが同じ署名を持っていない場合、実際に互いに移動することはできません(私は思います)。そういうわけで、missingno の回答を選択しませんでした。ディスパッチャを自分で実装する必要があったため、他の部分的な回答を受け入れていません。これは、私が行った変換の例です。それはそのようなものでした:

addSample = function(tile,sample,num_samples,which_sample){}
render = function(tile){}
...

そして次のようになりました:

addSample = function(config,dispatcher){
     var tile = config["tile"];
     var sample = config["sample"];
     var num_samples = config["num_samples"];
     var which_sample = config["which_sample"];

     something.call(function(){
        //async part of code
        dispatcher.check(); // important! 
     });
}
render = function(config,dispatcher){
     var tile = config["tile"];
     something.call(function(){
        //async part of code
        dispatcher.check(); // important! 
     });
}
...

最後の行として dispatcher.check() を呼び出さない場合、各間隔 (以下を参照) で TODO 呼び出しが 1 つだけになります。しかし、残っているそれらすべてが必要です。それから私はディスパッチャを持っています:

var dispatcher = { };
dispatcher.current = 0;
dispatcher.total = 0 ;
dispatcher.next = function(){
    this.current++;
}
dispatcher.hasMore = function(){
    return dispatcher.current<dispatcher.total;
}
dispatcher.addNew = function(todo){
    this.total++;
    this[this.total] = todo;
    return this;
}
dispatcher.exec = function(){
    this[this.current].func(this[this.current].config,this);    
    delete this[this.current]; //deletes the TODO just invoked
}

dispatcher.check = function(){
    if (this.hasMore()){
        dispatcher.next();
        dispatcher.exec();
    }
}

次に、ディスパッチャーにさらに TODO ジョブを追加し、それぞれに func: funcName と config があり、非同期関数が以前持っていたすべての入力が含まれています。

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}});

間隔はチェックしてから、残っているすべての TODO を 1 つずつ呼び出します。TODO のグループがしばらくしてから来ると、setInterval はそのグループを一度にその順序で選択します。

setInterval(function(){dispatcher.check();},1000);

お時間をいただきありがとうございました!私がしたように、誰かがそれを役に立つと思うことを願っています。

于 2013-06-24T00:28:28.267 に答える