protected function prepareAsyncVia() {
        // lazy loading of a relation
        $where = $this->where;

        $promise = new LazyPromise(function() {
            return resolve(true);
        });

        if ($this->via instanceof self) {
            // via junction table
            $promise->thenLazy(
                function() {
                    return $this->via->findJunctionRows([$this->primaryModel]);
                }
            )->thenLazy(
                function($viaModels) {
                    $this->filterByModels($viaModels);
                    return true;
                }
            );
        } elseif (is_array($this->via)) {
            // via relation
            /* @var $viaQuery ActiveQuery */
            list($viaName, $viaQuery) = $this->via;
            $viaModelsPr = $viaQuery->multiple ? $viaQuery->all() : $viaQuery->one();
            $viaModelsPr->otherwise(function() use (&$viaQuery) {
                return $viaQuery->multiple ? [] : null;
            });
            $promise->thenLazy(
                function() use ($viaModelsPr) {
                    return $viaModelsPr;
                }
            )->thenLazy(
                function($viaModels) use ($viaName, &$viaQuery) {
                    $this->primaryModel->populateRelation($viaName, $viaModels);
                    if (!$viaQuery->multiple) {
                        $viaModels = $viaModels === null ? [] : [$viaModels];
                    }
                    return $viaModels;
                }
            )->thenLazy(
                function($viaModels) {
                    $this->filterByModels($viaModels);
                    return true;
                }
            );
        } else {
            $this->filterByModels([$this->primaryModel]);
        }
        return $promise->thenLazy(
            function() use (&$where) {
                $query = Query::create($this);
                $this->where = $where;
                return $query;
            }
        );
    }