Ember.js: Параметры запроса сбрасываются до значений по умолчанию при первоначальном рендеринге, если transitionTo вызывается в beforeModel

Созданный на 21 авг. 2015  ·  48Комментарии  ·  Источник: emberjs/ember.js

Надеюсь, название и эта JS-корзина говорят сами за себя. TL; DR; если вы вызываете transitionTo в beforeModel при начальной загрузке (нажав кнопку обновления), параметры запроса будут сброшены до состояния по умолчанию.

http://emberjs.jsbin.com/kicoro/1#

Bug Query Params

Самый полезный комментарий

Также вижу эту ошибку на 2.14.

Все 48 Комментарий

@raytiley Мне интересно, существует ли это ошибка как в 1.13, так и в 2.0. Также пример работает с предыдущей версией Ember, то есть 1.12?

@raytiley - Как вы думаете, это связано с https://github.com/emberjs/ember.js/issues/12107 ( основная проблема)?

@rwjblue Это может быть то же самое, мне действительно нужно копнуть немного глубже, чтобы понять, где должно происходить желаемое поведение. Основная проблема заключается в том, что qpMeta для каждого обработчика не обновлялись до начала нового перехода. Это происходит в событии finalizeQueryParamChange (https://github.com/emberjs/ember.js/blob/c9bbfb6081e6c145132addda84ed385b940979ff/packages/ember-routing/lib/system/route.js#L762), которое запускается роутер.

Мое основное понимание без написания теста таково. Сначала вы вводите маршрут с URL-адресом с параметрами запроса ... это создает новый переход, но никогда не вызывает finalizeQueryParamChange потому что он прерывается вызовом transitionTo в одном из хуков маршрутов. Этот новый переход подготавливает queryParams (https://github.com/emberjs/ember.js/blob/master/packages/ember-routing/lib/system/router.js#L603), но поскольку qpMeta никогда не обновлялся исходный переход использует все значения по умолчанию. Поэтому вы придерживаетесь значений по умолчанию :(

@pixelhandler Я не проверял другие версии, но я не думаю , что эта область коды изменилась коренным образом , для @trek «s недавние работы по перемещению queryParam конфигурации к маршрутизатору исключения. Я не верю, что это произошло, но, возможно, это хорошее место, чтобы изменить это поведение.

В идеале, я думаю, нам нужно завершить и изменить queryParam для текущего перехода при вызове transitionTo во время активного перехода. Поскольку вы можете передать queryParams в transitionTo он по-прежнему дает новому переходу возможность переопределить любые изменения queryParam предыдущего вызова перехода.

Для всех, кто следит за мной, в качестве обходного пути я смог запланировать transitionTo на цикл выполнения в afterRender , чтобы сохранить мои queryParams. Вы получаете раздражающую вспышку нежелательного маршрута, но это лучше, чем потеря всего входящего состояния. У меня это было только в нескольких местах в моем приложении, поэтому это не является для меня огромным приоритетом. Исправить это в ближайшее время, просто хотел сообщить об этом.

+1

@raytiley Я пробовал ваш обходной путь, но мои queryParams все еще удаляются следующим образом:

Ember.run.scheduleOnce('afterRender', this, function() {
    this.replaceWith('campaign.show.onestep', { queryParams });
});

Это правильный синтаксис, да?

@noslouch Вы также можете попробовать очередь routerTransitions .

У меня нет этой конкретной проблемы, но у меня есть проблемы с transitionTo({queryParams: { foo: 'bar' }}); внутри beforeModel при начальной загрузке. Я только начал получать ошибку в 2.1, все было нормально в 2.0. Так или иначе, мои параметры запроса, сохраняются и приложение ведет себя , как и ожидалось, только странно , что это ошибка.

Из фантома:

TypeError: undefined is not an object (evaluating 'handlerInfos[handlerInfos.length - 1].name')

Из хрома:

TypeError: Cannot read property 'name' of undefined
    at _emberRuntimeSystemObject.default.extend.actions.finalizeQueryParamChange (ember.debug.js:25996)
    at Object.triggerEvent (ember.debug.js:28253)
    at Object.trigger (ember.debug.js:50891)
    at finalizeQueryParamChange (ember.debug.js:50040)
    at Object.Router.queryParamsTransition (ember.debug.js:49418)
    at Object.getTransitionByIntent (ember.debug.js:49331)
    at Object.Router.transitionByIntent (ember.debug.js:49436)
    at doTransition (ember.debug.js:50008)
    at Object.Router.transitionTo (ember.debug.js:49505)
    at _emberRuntimeSystemObject.default.extend._doTransition (ember.debug.js:27978)

@kmiyashiro +1, у меня точно такая же проблема после обновления до 2.1.0

TypeError: Cannot read property 'name' of undefined
    at _emberRuntimeSystemObject.default.extend.actions.finalizeQueryParamChange (ember.debug.js:25996)
    at Object.triggerEvent (ember.debug.js:28253)
    at Object.trigger (ember.debug.js:50891)
    at finalizeQueryParamChange (ember.debug.js:50040)
    at Object.Router.queryParamsTransition (ember.debug.js:49418)
    at Object.getTransitionByIntent (ember.debug.js:49331)
    at Object.Router.transitionByIntent (ember.debug.js:49436)
    at doTransition (ember.debug.js:50008)
    at Object.Router.transitionTo (ember.debug.js:49505)
    at _emberRuntimeSystemObject.default.extend._doTransition (ember.debug.js:27978)

Меня это тоже только что укусило, если я добавлю это к совершенно не связанному маршруту

import Ember from 'ember';

export default Ember.Route.extend({
  beforeModel: function() {
    this.transitionTo('works');
  }
});

Затем мои параметры запроса, кажется, удаляются, и я получаю эту ошибку ...

TypeError: Cannot read property 'name' of undefined
    at _emberRuntimeSystemObject.default.extend.actions.finalizeQueryParamChange (ember.debug.js:25680)
    at Object.triggerEvent (ember.debug.js:27911)
    at Object.trigger (ember.debug.js:52341)
    at finalizeQueryParamChange (ember.debug.js:51490)
    at Object.Router.queryParamsTransition (ember.debug.js:50868)
    at Object.getTransitionByIntent (ember.debug.js:50781)
    at Object.Router.transitionByIntent (ember.debug.js:50886)
    at doTransition (ember.debug.js:51458)
    at Object.Router.transitionTo (ember.debug.js:50955)
    at _emberRuntimeSystemObject.default.extend._doTransition (ember.debug.js:27636)

Я использую Ember: 2.3.0-canary+3486f33c

благодаря

У меня это происходит на

Здесь тоже случается ...

Я с @kmiyashiro , вроде все работает, как ожидалось ... но я все еще получаю сообщение об ошибке в консоли. Я могу легко воссоздать это в твиддле. Просто загрузите следующее с открытой консолью. Вы можете видеть ошибку в ember 2.1 и 2.2, похоже, не появляется в 2.0.

https://ember-twiddle.com/86849f6610f3a68a9840?route=%2F%3Ftest%3Dfoo

Вот способ, который можно использовать для запуска переходов, пока эта ошибка остается нерешенной.

let RedirectAfterDidTransition = Ember.Mixin.create({
  redirectAfterDidTransition(...args) {
    this.router.one('didTransition', ()=>{
      this.router.transitionTo(...args);
    });
  }
});

export default Route.extend(RedirectAfterDidTransition, {
  afterModel() {
    this.redirectAfterDidTransition('index');
  }
});

Я клонировал указанный выше Twiddle и добавил пример https://ember-twiddle.com/2d49a9d1aa3ddaff6ef5?numColumns=1&route=%2F%3Ftest%3Dfoo

Примечание: это будет ждать завершения перехода перед выполнением перенаправления.

Вот более простая версия, которая, кажется, также работает в моем коде

import Ember from 'ember';

// This mixin provides `abortAndTransitionTo` method that'll abort the current
// transition and transition to specified parameters.
// It takes same arguments as Route#transitionTo
// it's necessary because of https://github.com/emberjs/ember.js/issues/12169
let AbortAndTransitionTo = Ember.Mixin.create({
  abortAndTransitionTo(...args) {
    this.router.router.activeTransition.abort();
    this.router.transitionTo(...args);
  }
});

export default Route.extend(AbortAndTransitionTo, {
  afterModel() {
    this.abortAndTransitionTo('index');
  }
});

@taras не

Мой обходной путь - просто поймать ошибку и зарегистрировать ее, поскольку я не смог найти никаких побочных эффектов.

beforeModel(transition) {
  this._super(...arguments);

  // Logic to set presetParams (dynamic initial params)

  this.transitionTo({ queryParams: presetParams })
    .catch(() => {
      log('Ember 2.1 query param issue: https://github.com/emberjs/ember.js/issues/12169');
    });
}

@kmiyashiro, что ты имеешь в виду: "тратить

Я предполагаю, что вы выполняете выборку (поиск / запрос) в model , поэтому, если ваш запрос params refresh модель, он повторно получит модель с обновленными параметрами. Если вы используете transitionTo внутри beforeModel , он неявно прерывает активный переход. К сожалению, есть _много_ ошибок при переходе на новые параметры запроса в любом из этих хуков:

https://github.com/emberjs/ember.js/issues/10577
https://github.com/emberjs/ember.js/issues/12102
https://github.com/emberjs/ember.js/issues/10945

У нас может быть другой вариант использования. Если вы хотите изучить это дальше, вы можете связаться со мной в Slack сообщества Ember, или мы можем подключиться через http://j.mp/EmberSherpa

Возникла та же проблема, хотя я не вызываю явно transitionTo или replaceWith , и при этом маршрут ничего не делает с Ember-Data или какой-либо логикой выборки модели. Я просто перехожу непосредственно к маршруту с параметром запроса, который сопоставляется с логическим свойством в контроллере маршрута. Это начало происходить только тогда, когда я обновился до Ember 2.1+. Переход вроде завершен и все работает нормально, но в консоль вываливается ошибка. Я пробовал несколько из вышеперечисленных решений, а также переопределил некоторые частные методы прототипа на маршрутизаторе, но поскольку ошибка исходит от router.js, который скрыт в замыканиях через маршрутизатор Ember Router, я не могу надежно подавить Ошибка.

Поскольку я не могу надежно подавить ошибку, я не могу перейти на Ember 2.1 или 2.2, так как эта ошибка приводит к сбою некоторых из моих модульных тестов, что не нравится моей системе CI.

TypeError: Cannot read property 'name' of undefined
    at _emberRuntimeSystemObject.default.extend.actions.finalizeQueryParamChange (ember.debug.js:25264)
    at Object.triggerEvent (ember.debug.js:27476)
    at Object.trigger (ember.debug.js:51925)
    at finalizeQueryParamChange (ember.debug.js:51074)
    at Object.Router.queryParamsTransition (ember.debug.js:50452)
    at Object.getTransitionByIntent (ember.debug.js:50365)
    at Object.Router.transitionByIntent (ember.debug.js:50470)
    at doTransition (ember.debug.js:51042)
    at Object.Router.transitionTo (ember.debug.js:50539)
    at _emberRuntimeSystemObject.default.extend._doTransition (ember.debug.js:27201)

Я смог подавить ошибку, установив исправление для маршрутизатора:

export default Ember.Router.extend({
    _isRouterPatched: false,

    // monkey-patch the Ember.Router to suppress the error thrown by this bug:
    // https://github.com/emberjs/ember.js/issues/12169
    startRouting() {
        let result = this._super.apply(this, arguments);

        if (!this.get('_isRouterPatched')) {
            let _proto = Object.getPrototypeOf(this.router),
                _original = _proto.queryParamsTransition;

            _proto.queryParamsTransition = function () {
                try {
                    return _original.apply(this, arguments);
                } catch (e) {
                    console.warn(
                        'Ember 2.1 queryParams bug:',
                        'https://github.com/emberjs/ember.js/issues/12169',
                        e
                    );
                }
            };

            this.set('_isRouterPatched', true);
        }

        return result;
    }
});

Со мной происходит на Ember 2.2.2. Я ловлю и регистрирую ошибку, так как побочных эффектов нет.

Возможно, это не самое элегантное решение, но, похоже, оно работает в Ember 1.13:

// app/instance-initializers/global-query-params.js

import Ember from 'ember';
import _ from 'lodash';

const RouteSupport = Ember.Mixin.create({
  transitionTo: superWithGlobalQueryParams,
  replaceWith: superWithGlobalQueryParams
});

function getQueryParams(...names) {
  return names.reduce(function(result, name) {
    const regex = new RegExp(`[?&]${name}=([^?&]+)`);
    const md = regex.exec(window.location.search || '');
    if (md) { result[name] = md[1]; }
    return result;
  }, {});
}

function superWithGlobalQueryParams(...args) {
  const globalQueryParams = getQueryParams('tango-version');

  if (args.length === 1) {
    // transitionTo('some.route');
    args.push({ queryParams: globalQueryParams });
  } else if (args.length === 2 && args[1].queryParams) {
    // transitionTo('some.route', { queryParams: { ... } });
    args[1].queryParams = _.extend({}, globalQueryParams, args[1].queryParams);
  } else if (args.length === 2) {
    // transitionTo('some.route', someModel);
    args.push({ queryParams: globalQueryParams });
  } else {
    // transitionTo('some.route', someModel, { queryParams: { ... } });
    args[2].queryParams = _.extend({}, globalQueryParams, args[2].queryParams);
  }

  return this._super(...args);
}

export default {
  name: 'global-query-params',

  initialize() {
    Ember.Route.reopen(RouteSupport);
  }
};

Если вы не хотите поддерживать там список разрешенных параметров запроса, вы можете просто проанализировать их все, используя что-то вроде этого .

То же самое происходит без прямого вызова transitionTo

beforeModel(transition) {
  let token = transition.queryParams.token;
  return this.get('session').authenticate('authenticator:custom', token).then(...).catch(...);
}

ember-simple-auth пытается перейти на '/' в случае успешной аутентификации.

Ember 2.3.0.beta2

Со мной тоже. Использование решения @taras abortAndTransitionTo .

Ember: 2.2.0

Я вижу в своем коде вариант этой ошибки.

Ошибка, которую я вижу, происходит, когда я повторно загружаю страницу с параметрами запроса. Сама страница находится во вложенном маршруте - методы setupController в родительском и родительском маршрутах вызывают transitionTo , чтобы перейти к правильному маршруту. Переходы маршрутизации работают нормально при посещении корневого URL-адреса приложения - переходы происходят, и URL-адрес устанавливается правильно, включая параметры запроса, и ошибки не возникает.

Я вижу конкретную ошибку:

TypeError: Cannot set property '_qpDelegate' of undefined
    at _emberRuntimeSystemObject.default.extend.actions.finalizeQueryParamChange (ember.debug.js:26398)
    at Object.triggerEvent (ember.debug.js:28636)
    at Object.trigger (ember.debug.js:53210)
    at finalizeQueryParamChange (ember.debug.js:52359)
    at Object.Router.queryParamsTransition (ember.debug.js:51737)
    at Object.getTransitionByIntent (ember.debug.js:51650)
    at Object.Router.transitionByIntent (ember.debug.js:51755)
    at doTransition (ember.debug.js:52327)
    at Object.Router.transitionTo (ember.debug.js:51824)
    at _emberRuntimeSystemObject.default.extend._doTransition (ember.debug.js:28347)

Рассматриваемый объект undefined - это controller (извлекается из route.controller в цикле, который проходит через qpMeta.qps внутри finalizeQueryParamChange .

Когда я устанавливаю точку останова, я вижу, что finalizeQueryParamChange вызывается дважды. Только в первый раз объект controller оказывается неопределенным.

Выброшенное исключение кажется безвредным, поэтому для меня

Ember: 2.4.2

Исправление включено в v2.4.4.

Хм, после обновления "ember" до "2.4.4" в моем bower.json и удаления обходного пути AbortAndTransitionTo Тараса у меня все еще есть ошибка TypeError: Cannot read property 'name' of undefined . Та же трассировка стека, что и в этом комментарии .

@ john-kurkowski, можешь ли ты попытаться собрать вместе простое воспроизведение ember-twiddle / jsbin? Теперь, когда весь этот код свеж в моей голове, я, вероятно, смогу довольно быстро разобраться с воспроизведением.

@ john-kurkowski Я думаю, это исправит эту ошибку: https://github.com/emberjs/ember.js/pull/13273

Надеюсь закончить тестирование завтра, а потом приставлю @rwjblue для слияния :)

По-прежнему возникает проблема в Ember 2.6.0

Хм, я использую 2.4.6, но проблема все еще возникает.

@mschinis прочтите это: https://github.com/emberjs/ember.js/pull/13600

Отличное спасибо

У меня все еще происходит на 2.7.0.

У меня все еще происходит на 2.9.0. afterModel() transitionTo(another route) работал нормально, но transitionTo(this-route-with-different-query-params) не удалось с TypeError: Cannot read property 'name' of undefined . Использование метода redirect() дало тот же результат, что и replaceWith() вместо transitionTo() . Чтобы заставить его работать, мне пришлось установить хэш маршрута queryParams следующим образом:

queryParams: {
  category: {
    refreshModel: true
  }
}

но это болезненно, потому что я не хочу обновлять модель. (модель, которая у меня есть, в порядке!) Но с этим изменением все варианты приведенного выше кода ( redirect() и replaceWith() ) работают нормально, хотя replaceWith() фактически не заменяет элемент истории.

Все еще происходит со мной в 2.10.2, но с немного другой трассировкой стека:

TypeError: Cannot read property 'name' of undefined
    at Class._queryParamsFor (ember.debug.js:27449)
    at Class.finalizeQueryParamChange (ember.debug.js:25269)
    at Router.triggerEvent (ember.debug.js:27862)
    at trigger (ember.debug.js:55572)
    at finalizeQueryParamChange (ember.debug.js:57560)
    at Router.queryParamsTransition (ember.debug.js:56907)
    at Router.getTransitionByIntent (ember.debug.js:56816)
    at Router.transitionByIntent (ember.debug.js:56925)
    at doTransition (ember.debug.js:57527)
    at Router.transitionTo (ember.debug.js:57001)

Полагаю, этот вопрос следует снова открыть.

Та же проблема в 2.10.0
afterModel(model) { if (model.get('length') === 0) { this.transitionTo('users', { queryParams: { page: 1 }}); } }

Я вижу ту же трассировку стека, что и @ slava-dzyba в 2.10.2.

Видя ту же ошибку в 2.12.1. Пробовали описанные выше обходные пути и предлагали исправления, но безрезультатно.

Также вижу эту ошибку на 2.14.

Мое обходное решение - вручную прервать переход перед переходом на другой маршрут.

  beforeModel(transition) {
    // For example, first time we transition
    if (transition.sequence === 0) {
      transition.abort();
     // replace with whatever route/query params work for you
      this.replaceWith('index');
    }
  }

Кажется, работает с версиями Ember 2.18 и 3.0. Надеюсь это поможет.

Видя такую ​​же проблему с 2.18 и стеком от @sdzyba

Я пробовал обходной путь transition.abort() от @jorblume, но безрезультатно, выполнение, кажется, останавливается и никогда не выполняет transitionTo

Та же проблема с 3.3 при использовании transitionTo() в afterModel() , мое решение:

            if (transaction.sequence === 0) {
                transaction.abort();                
                this.transitionTo('route', {queryParams: newQueryParams});    
            }

Привет!

Я могу подтвердить, что обходной путь

С уважением,
Даниэль.

Я решил это, вернувшись сразу после this.transitionTo() :

model(){
...
if(someCondition){
   return this.transitionTo({ queryParams: error.data.params });
}
...
}

Если оператор return находится в строке ниже this.transitionTo() , проблема сохраняется.
Кстати, я вообще не использовал transition.abort() потому что он останавливает любые другие предстоящие переходы - приложение зависает.

Я получил ту же ошибку, но в моем случае мне пришлось заменить использование this.replaceWith('/'); фактическим именем маршрута this.replaceWith('my.route') после добавления вложенного маршрута для маршрута X, например:

this.route(..., { path: '/' }, function() {
   this.route(..., { path: '/' })
});

После добавления вложенного маршрута с помощью / приложение evaluating 'handlerInfos[handlerInfos.length - 1].name' .

Ember.js v3.5.0 .

Есть новости по этому поводу? Не удалось заставить работать какие-либо обходные пути. На Ember v3.4.0

Была ли эта страница полезной?
0 / 5 - 0 рейтинги