JS: возможно ли передавать объекты со ссылками на другие объекты из webworkers?

#javascript #web-worker

#javascript #web-worker

Вопрос:

Часть моей программы включает синтаксический анализ текста в структуры данных, которые используют ссылки на другие объекты внутри структуры. Из-за того, как это вписывается в программу, это был бы идеальный кандидат для WebWorkers, поскольку это можно сделать, пока вычисляются другие вещи, и не полагается на какие-либо другие данные, кроме тех, что переданы в него.

Давайте, например, воспользуемся следующим кодом webworker:

 self.onmessage = (e) => {
    let a;
    let b;
    let c;

    a = {
        obj1: b,
        obj2: c
    }

    b = {
        obj1: a,
        obj2: a
    }

    c = {
        obj1: b,
        obj2: b
    }

    let myArr = [a, b, c];

    self.postMessage(myArr);
}
  

в настоящее время, если я создаю это в web worker и возвращаю myArr , obj1 и obj2 каждого из элементов не определены. Есть ли какой-либо способ получить эти ссылки из webworker?

Комментарии:

1. Можете ли вы JSON.stringify(myArr) в worker, а затем JSON.parse(e.message) в main file?

2. Хм, странно. Я думал, что это то, что JS делал в любом случае за кулисами, но я думаю, что нет. В любом случае, это на самом деле не работает. Даже после изменения кода для создания экземпляра a, b и c с использованием класса, просто кажется, что он проходит через дерево и копирует значения объекта, Т.Е.: если я внесу изменения в b then a.obj1 (какие ссылки b), это изменение не отразится

Ответ №1:

Хорошо, я понял это. Я неправильно понимал, как работают ссылки, и это приводило к моим ошибкам.

проблема заключалась в том, что я переназначал объекты и разбивал ссылки, прежде чем отправлять их обратно в основной поток.

Поэтому вместо

 let a;
let b;

a = {ref: b}
b = {ref: a}
  

В приведенном выше примере b значение начинается с undefined , что означает, когда мы присваиваем его a.ref , a.ref = undefined , и когда мы присваиваем b.ref = a b сейчас b = {ref: {ref: undefined}}

Чтобы исправить это, мне нужно было убедиться, что переменные были сначала назначены их объектам

 let a = {ref: null}
let b = {ref: null}

a.ref = b;
b.ref = a;
  

Как только я исправил это, казалось, все работало нормально, и b теперь изменения обновляются a.ref в основном потоке. Это также было бы исправлено, если бы я просто объявил переменные как let a = new SomeClass()

Если вы столкнулись с подобной проблемой, НЕ ИСПОЛЬЗУЙТЕ JSON.stringify() ! Поначалу может показаться, что это работает, но на самом деле это глубокое копирование ваших ссылок на другие объекты, что означает, что изменение на b фактически не будет обновляться a.ref , поскольку a.ref теперь это просто копия b , а не ссылка.