Great question! Was waiting for it 
Solving that topic https://community.plotly.com/t/subject-how-to-process-calculations-with-a-queue-celery-rq-etc-and-display-results-immediately-after-completion/83280/4 I came to the solution, where I create new tasks in dash and send them with websockets to workers. With websockets workers inform me of progress and send me results, and I set that progress and results directly by element.innerText
Seems like I use all possible powers together: the power of Dash in quickly creating interfaces , the power of queues for heavy tasks, the power of websockets for quick messaging, and the power of javascript for quick manipulation with dom (set results).
All would be good, but when I add new tasks - all previous updates are cleared by the dash, it displays their starting inner states - with no results 
Demo:

And that is the main problem. And I started to dive into that issue.
Here is the code for creating tasks in Dash:
app.layout = dmc.NotificationsProvider(
[
dbc.Container(
[
# two stores, one to track which job was most recently started, one to
# track which job was most recently completed. if they differ, then
# there is a job still running.
# dcc.Store(id="submitted_store", data={}),
# dcc.Store(id="finished_store", data={}),
dcc.Interval(id="interval", interval=1000),
html.H2("MULTI Redis / RQ demo", className="display_4"),
html.P(EXPLAINER),
html.Hr(),
dbc.Textarea(value="1" * CNT_ELEMENTS, id="text", className="mb_3"),
dbc.Button(
"Upper case", id="button", color="primary", className="mb_3"
),
dbc.Collapse(
dbc.Progress(id="progress", className="mb_3"), id="collapse"
),
html.Hr(),
html.Div(
[
html.H1(f"WebSocket Update Example: {CNT_ELEMENTS} elements"),
# html.Div(["connecting"], id="connection_status"),
html.Div(id="log"),
html.Div(["notification_wrapper"], id="notification_wrapper"),
]
),
html.Hr(),
html.P(id="output_result"),
html.P(id="log_result"),
# adding websockets elements
]
)
]
)
@app.callback(
[
Output("output_result", "children"),
Output("log_result", "children"),
# Output("submitted_store", "data"),
Output("interval", "disabled"),
],
[Input("button", "n_clicks")],
[
State("text", "value"),
State("output_result", "children"),
# State("submitted_store", "data"),
],
)
def submit_to_multiple_tasks(n_clicks, text, output_result):
"""
Submit a job to the queue, log the id in submitted_store
"""
submitted_store = global_submitted_store
output_result = output_result or []
message = "empty_log"
if n_clicks:
logger.debug(f"submit_to_multiple_tasks {submitted_store=}")
ws_boss.notify_rendered(f"adding {len(text)} tasks")
for num, symbol in enumerate(text, 1):
id_ = f"{num}_{uuid.uuid4()}"
# queue the task
# queue.enqueue(slow_loop, text, job_id=id_)
queue.enqueue(slow_dash_div, symbol * 3, job_id=id_)
submitted_store[id_] = {"status": "queued"}
global_dynamic_progress_id.add(id_)
output_result.insert(
0,
html.Div(
[
html.Div(
[f"at {get_human_time_ms()} added {num}/{len(text)} {id_}"],
id={"index": id_, "type": "dynamic_first_message"},
),
html.Div(
["no progress"],
id={"index": id_, "type": "dynamic_progress"},
),
html.Div(
id={"index": id_, "type": "dynamic_result"},
),
],
),
)
# log process id in dcc.Store
message = f"{len(submitted_store)} {submitted_store=}"
ws_boss.notify_rendered(f"+added tasks")
logger.debug(message)
interval_disabled = False
return output_result, message, interval_disabled