def _set_data_node_output(self, node_id, node_attr, no_call, next_nds=None,
                              **kw):
        est, wait_in = self._get_node_estimations(node_attr, node_id)
        if not no_call:
            if node_id is PLOT:
                est = est.copy()
                est[PLOT] = {'value': {'obj': self}}
            sf, args = False, ({k: v['value'] for k, v in est.items()},)
            if not (wait_in or 'function' in node_attr):
                sf, args = True, tuple(args[0].values())
            try:
                value = async_thread(self, args, node_attr, node_id, sf, **kw)
            except SkipNode:
                return False
            if value is not NONE:
                self[node_id] = value
            value = {'value': value}
        else:
            self[node_id] = NONE
            value = {}
        if next_nds:
            wf_add_edge = self._wf_add_edge
            for u in next_nds:
                wf_add_edge(node_id, u, **value)
        else:
            n, has, sub_sol = self.nodes, self.workflow.has_edge, self.sub_sol
            def no_visited_in_sub_dsp(i):
                node = n[i]
                if node['type'] == 'dispatcher' and has(i, node_id):
                    visited = sub_sol[self.index + node['index']]._visited
                    return node['inputs'][node_id] not in visited
                return True
            succ_fun = [u for u in self._succ[node_id]
                        if no_visited_in_sub_dsp(u)]
            if succ_fun and succ_fun[0] not in self._visited:
                wf_add_edge = self._wf_add_edge
                for u in succ_fun:
                    wf_add_edge(node_id, u, **value)
        return True