3

私はウェブワーカーで遊んでいます。かなりの時間がかかる操作を持つ中規模のデータオブジェクトがいくつかあります。Web ワーカーは、これらの操作を並列化するための優れた方法のように思えますが、それらを Web ワーカーに渡す最善の方法を選択するのは難しいと感じています。Web ワーカーはオブジェクトをシリアライズおよびデシリアライズできますが、その場合、クラス メソッドは取り除かれます。もちろん、私は本当に彼らの方法を使いたいです。

問題は、メソッドの再アタッチを処理する良い方法は何ですか? 明らかに、渡されたオブジェクトにメソッドをコピーすることもできますが、これは取得したオブジェクトの種類を知っていることを意味します。さらに困難なことに、一部のオブジェクトには他のクラスのデータが含まれています。つまり、それらにメソッドを再アタッチする必要があります。最初に頭に浮かぶのは、JSON オブジェクトをパラメーターとして受け取る各クラスの代替コンストラクターを実装することです。その後、代替コンストラクターは、任意のデータ メンバーの JSON コンストラクターを再帰的に呼び出すことができます。

次に、最初に正しいコンストラクターをどのように選択するかという問題私が考えたアプローチには次のものがあります。

  1. クラスごとに1つずつ異なるWebワーカーを実装する(厄介)
  2. 正しいコンストラクターを呼び出すファクトリ メソッドを実装する (送信する前に、送信するオブジェクトのクラスを直接指定して送信したことを意味します) (より良いが、それでも扱いにくい)
  3. トップレベルのオブジェクトがどのクラスであるかを把握するために、型推測関数を実装します。(-_-)

誰かがより良いアイデアを持っていますか?

4

4 に答える 4

1

オプション 2 が最適なオプションのように思えます。自分自身をシリアライズおよびデシリアライズする方法を知っているクラスのメソッドの標準セットと、グローバルなシリアライゼーション ヘルパーを確立すると、これを簡単に行うことができます。次のコードを検討してください。

逆シリアル化 = (関数() {

    var レジストリ = {};

    var デシリアライズ = 関数 (obj) {
        var cls = obj['クラス'];
        var data = obj['データ'];

        var fn = レジストリ[cls];
        fn(データ)を返します;
    };

    deserialize.registerClass(name, fn) {
        レジストリ[名前] = fn;
    };

    逆シリアル化を返します。
});

そして、次のクラス:

/**
* 人物に関する情報
*/
var Person = function(firstName, lastName, age, phoneNumbers) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.age = 年齢;
    this.phoneNumbers = phoneNumbers;
};

Person.serializeName = '人';

/**
* Person のインスタンスをシリアル化する
*/
Person.prototype.serialize = function() {
    戻る {
        「クラス」: Person.serializeName、
        'データ': {
            'first_name': this.firstName,
            「last_name」、this.lastName、
            「年齢」: this.age,
            'phone_numbers': this.phone_numbers.map(function(number) { return number.serialize(); })
        }
    };
}

/**
* Person のインスタンスをデシリアライズする
*/
Person.deserialize(データ) {
    var phoneNumbers = data.phone_numbers.map(デシリアライズ);
    return new Person(data.first_name, data.last_name, data.age, phoneNumbers);
};

deserialize.register(Person.serializeName, Person.deserialize);

を使用して任意の Person インスタンスをdata = person.serialize();シリアル化し、これをワーカーに送信し、シリアルperson = deserialize(data);化形式でデータを生成するものはすべて逆シリアル化できます。逆シリアル化する前に、それがどのような種類のクラスであるかを知る必要はありません - タイプは運ばれますデータと共に。で示されているように、ネストされたデータ型も可能person.phoneNumbersです。PhoneNumber クラスの実装は次のようになります。

/*
* 電話番号
*/
var PhoneNumber = function(number, numberType) {
    this.number = 番号;
    this.numberType = numberType;
}

PhoneNumber.prototype.serializeName = '電話番号';
/**
* PhoneNumber のインスタンスをシリアル化する
*/
PhoneNumber.prototype.serialize = function() {
    戻る {
        「クラス」: PhoneNumber.serializeName、
        'データ': {
            「番号」: this.number,
            'number_type': this.numberType,
        }
    };
}

/**
* PhoneNumber のインスタンスをデシリアライズする
*/
PhoneNumber.deserialize(データ) {
    var phoneNumbers = data.phone_numbers.map(デシリアライズ);
    新しい電話番号を返します (data.first_name, data.last_name, data.age, phoneNumbers);
};

deserialize.register(PhoneNumber.serializeName, PhoneNumber.deserialize);

繰り返しますが、データ チャンクを逆シリアル化するためのすべての情報はチャンクにあるため、データを に送信するdeserializeと、何かのインスタンスが返されます。通常のコードと Webworker コードでクラスを再利用すると、最初に使用したインスタンスの同一のコピーが返されます。

于 2013-03-22T00:59:30.793 に答える
1

どうやら、私が本当に必要としていたのは__proto__、Javascript のプロパティを理解することだけだったようです。これにより、オブジェクトが Web ワーカーに渡された後、またはローカル ストレージから取得された後に、オブジェクトのクラス メソッドの可用性を再確立できます。

function reattachMethods(serialized,originalclass) {
    serialized.__proto__ = originalclass.prototype; 
}

上記の解決策のいくつかの問題は、すべてのデータを正しい形式で既に持っているにもかかわらず、オブジェクトを再作成/コピーすることになることです。n 個の要素を含むオブジェクトがある場合、n 個のオブジェクトがシリアル化され、ブラウザーから Web ワーカーに送信された後に、新しいオブジェクトにコピーする必要がある n 個の要素です。これは明らかに理想的ではありません。ダブル アンダースコア プロトは、すべての主要なブラウザーに実装された非標準機能であり、次の JavaScript 標準の一部として発表されました。

于 2013-07-08T04:41:55.860 に答える
0

vkThread プラグインだと思います

http://www.eslinstructor.net/vkthread/

この問題を解決するのに役立ちます。このプラグインを使用すると、任意の関数 (オブジェクトのメソッドを含む) を別のスレッド (ワーカー) で実行できます。

別の便利なプラグインは JSONfn です

http://www.eslinstructor.net/jsonfn/

メンバー関数を使用して JavaScript オブジェクトをシリアル化できます。

お役に立てれば、

--ヴァディム

于 2013-07-31T05:44:37.307 に答える
0

最も簡単な方法は、プレーン データを Web ワーカーに渡し、そのデータを使用して Web ワーカー内の実際の作業に必要なカスタム オブジェクト (クラスなど) をインスタンス化することです。これらのカスタム クラスのコードは、Web ワーカーが利用できる必要があります。

次に、メイン スレッドと Web ワーカーの間の境界を越えてメソッドを渡そうとしていません (実際にできることではありません)。

オプション 2 がこれに最も近いように聞こえます。データを Web ワーカーに渡し、そのデータから作成するオブジェクトの種類を認識するコードを Web ワーカーに持たせるか、データを分析して実行する必要がある作業に適したタイプのオブジェクトを作成できるファクトリ関数を使用します。

オプション 1 が複雑になる理由はわかりません。並行して実行する実行スレッドごとに個別の Web ワーカーが必要ですが、さまざまな種類の作業に異なる Web ワーカーは必要ありません。Web ワーカーは、適切なコードが与えられれば、あらゆる種類の作業を行うことができます。

オプション 3 の「推測」は好きではありません。作成するオブジェクトのタイプを Web ワーカーに知らせたい場合は、そのデータを Web ワーカーに明示的に渡します。推測する理由はありません。

于 2013-03-22T00:21:28.137 に答える