2

ソケット APIを使用して Chrome 拡張機能を作成しています(ただし、このドキュメントは古くなっていますが、API の最新バージョンはこちらにあります)。コードを整理するのは非常に難しいことがわかりました。

すべてのメソッドは名前空間の下にあります。簡単にするために以下をchrome.experimental.socket使用します。socket

socket.create("tcp", {}, function(socketInfo){
    var socketId = socketInfo.socketId;

    socket.connect(socketId, IP, PORT, function(result){
        if(!result) throw "Connect Error";        

        socket.write(socketId, data, function(writeInfo){
            if(writeInfo.bytesWritten < 0) throw "Send Data Error";

            socket.read(socketId, function(readInfo){
                if(readInfo.resultCode < 0) throw "Read Error";
                var data = readInfo.data; // play with the data
                // then send the next request
                socket.write(socketId, data, function(writeInfo){
                    socket.read(socketId, function(readInfo){
                        // ............
                    });
                });
            });
        })
    });
})

socket.writeとは両方ともsocket.read非同期であるため、コールバックをネストして、前の要求が正しい応答を取得した後に次の要求が送信されるようにする必要があります。

これらのネストされた関数を管理するのは本当に難しいです。どうすれば改善できますか?

アップデート

send次のように使用できるメソッドが必要です。

send(socketId, data, function(response){
    // play with response
});
// block here until the previous send get the response
send(socketId, data, function(response){
    // play with response
});
4

2 に答える 2

1

これ(のようなもの)はどうですか?

var MySocket = {
  obj: null,
  data: null,
  start: function() { ... some code initializing obj data, ending with this.create() call },
  create: function() { ... some code initializing obj data, ending with this.connect() call },
  connect: function() { ... some connection code, ending with this.write() call },
  write: function() { ... some writing code that updates this.data, ending with this.read() call },
  read: function() { ... you probably get the idea at this point )) ... },
};

MySocket.start()このオブジェクトは、または何かと一緒に使用できます。アイデアは、すべてのデータ (およびネストされた呼び出し) を単一の (ただし、グローバルに使用できる可能性は低い) オブジェクト内にカプセル化することです。

さらに、2 つのオブジェクトを作成することもできます。1 つは純粋に書き込み用で、もう 1 つは純粋に読み取り用で、それぞれが独自の で動作し、dataそれら (およびそれらの相互呼び出し) を 1 つの SocketManager オブジェクトにラップします。

于 2012-05-21T14:27:27.330 に答える
0

関数が渡された関数を使用した SetInterval 呼び出しで終了する、非同期継続渡しスタイルの使用を検討してください。次に、このメカニズムを使用して、2 つの関数を絡み合わせて相互に呼び出す関数を作成します。その根性は次のようになります。

var handle;
// pairs two functions
function pair(firstfunc, secondfunc, startarg) {
  var callbackToFirst = function(valuetofill) {
    handle = setInterval(firstfunc(valuetofill,callbackToSecond));
  };
  var callbackToSecond = function(valuetofill) {
    handle = setInterval(secondfunc(valuetofill,callbackToFirst));
  };

  callbackToFirst(startarg);
}

ここで行っているのは、1 つの引数を受け取る相互呼び出しコールバックのペアを作成することです。これらのコールバックには、2 つの相互呼び出し関数への参照が含まれています。次に、最初のコールバックを呼び出してプロセスを開始します。

読み取り関数と書き込み関数のサンプル ペアのペアを作成します (外側のオブジェクト定義で socketId を設定したと仮定します)。

// starts read/write pair, sets internal variable 'handle' to 
//   interval handle for control
function startReadWrite(initialarg, myDataFunc) {
    var readcall = function(value, func) {
        readSocket(getData(myDataFunc(func)));
    };
    var writecall = function(value, func) {
        writeSocket(checkBytesWritten(func));
    };
    handle = pair(readcall, writecall, initialarg);
}

オブジェクトの残りの部分は次のようになります。

function myIO() {
    var socketInfo, socketId, handle;

    function create(func) {
        socket.create('tcp',{},function(thisSocketInfo) {
            socketInfo = thisSocketInfo;
        }
        setInterval(func(this),0);
    }

    function connect(IP, PORT, func) {
        socket.connect(p_socketId, IP, PORT, function() {
            if(!result) throw "Connect Error";
                setInterval(func(result),0);
            });
    }

    function readSocket(func) {
        socket.read(p_socketId, function(readInfo){ 
            setInterval(func(readInfo),0);
        });
    }

    function writeSocket(data, func) {
        socket.write(p_socketId, data, function(writeInfo){
            setInterval(func(writeInfo),0)
        });
    }

    function checkBytesWritten(writeInfo, func) {
        if(writeInfo.bytesWritten < 0) throw "Send Data Error";
        setInterval(func(writeInfo),0);
    }

    function getData(readInfo, func) {
        if(readInfo.resultCode < 0) throw "Read Error";
        var data = readInfo.data;
        setInterval(func(data),0);
    }


    //** pair and startReadWrite go here **//

}

最後に、全体を設定するための呼び出し:

var myIOobj = new myIO();
myIOobj.create(startReadWrite(myDataFunc));

ノート:

  1. これはスタイルを示すためのものであり、コードを準備するためのものではありません! コピーして貼り付けるだけではいけません。
  2. いいえ、私はこれをテストしていません。私はJavaScriptを行っていますが、Chrome APIはまだ行っていません。コールバック メカニズムなどに注目しています。
  3. コールバックの異なるクラスには注意してください。単一の値 (おそらく API で定義されている) を取る単一引数コールバック (読み取りおよび書き込みコールバックなど) と、引数と最後に呼び出す関数を取る 2 つの引数コールバック (ほとんどのメソッドと同様) です。
  4. getData メソッドはコールバックを受け取り、dataそれに渡します。このコールバック (myDataFunc) は、実際にデータを使用する関数です。コールバックを 2 番目の引数として取り、それを同期的または非同期的に呼び出す必要があります。

TLDR: ネストを避けるために、非同期呼び出しの使用を検討してください。必要に応じて、このスタイルを使用して 2 つの関数を継続的に呼び出すメカニズムのあいまいな例を示しました。

私はこれを非同期と呼んでいますが、setInterval 呼び出しはシリアルに実行されますが、重要なのは、ネストを使用して無限のレイヤーを追加するのではなく、親呼び出しが完了した後にスタックがクリアされることです。

于 2012-05-21T16:24:55.237 に答える