【问题标题】:code in willTransition callback executed after model callback after a window.alertwillTransition 回调中的代码在 window.alert 之后的模型回调之后执行
【发布时间】:2015-08-02 19:55:18
【问题描述】:

我最近遇到了 Ember.js 的一个错误。基本上,当我在 Firefox 中单击浏览器后退按钮时,Ember.js 会以错误的顺序执行代码。 willTransition回调中的代码在alert("...");之后的代码是在model回调之后执行的,通常应该在alert("...");返回之后执行。

代码是:

App = Ember.Application.create();
App.Router.reopen({
  location: 'history'
});
App.Router.map(function() {
  this.route('foo');
});
App.IndexRoute = Ember.Route.extend({
  actions:{
    willTransition: function(transition){
      console.log('start IndexRoute#willTransition');
      alert('See console logs');
      console.log('end IndexRoute#willTransition');
    }
  }
});
App.FooRoute = Ember.Route.extend({
  model: function() {
    console.log('start FooRoute#model');
    return [];
  }
});

可以在此处找到有关如何重现错误的说明:https://github.com/goooooouwa/location/blob/master/README.md

在 JSBin 上使用 Firefox(OS X 上的版本 12+,Windows 上的版本 7+)查看此错误:http://emberjs.jsbin.com/tefoka/

【问题讨论】:

  • 这个错误似乎是由this Firefox(版本38.0.1)错误引起的。

标签: firefox ember.js alert back-button html5-history


【解决方案1】:

此行为的根本原因是this Firefox 错误。

此错误如何导致相关行为

幕后发生了什么

  1. 用户点击浏览器后退按钮后,URL 发生变化,浏览器历史记录随之发生变化,触发PopStateEvent,然后Ember 使用onUpdateURL() 回调处理此事件
  2. 作为回调,Ember 通过调用 this._doURLTransition('handleURL', url); 开始转换
  3. 在转换内部,会创建一个 Promise 来确定此转换的解决方案。 Ember 通过调用run.backburner.schedule('actions', function(){...}) 在runloop 中调度promise,因为没有创建runloop,所以将通过调用Backburner.createAutoRun() 创建一个autorun
function createAutorun(backburner) {
  backburner.begin();
  backburner._autorun = global.setTimeout(function() {
    backburner._autorun = null; 
    backburner.end();
  });   
}

在自动创建的 runloop 结束之前,会执行以下代码:

willTransition: function(transition){
  console.log('-------------- 1. start IndexRoute#willTransition -------------- ');
  alert('See console logs');
  console.log('-------------- 2. end IndexRoute#willTransition -------------- ');
}

当 runloop 结束时,flush 过程开始,并执行以下代码:

model: function() {
  console.log('-------------- 3. start FooRoute#model -------------- ');
  return [];
}

简化版

上面的代码本质上是一样的:

console.log('processing: task #1');
setTimeout(function(){
  console.log('processing: task #3');
},0);
alert('See console logs');
console.log('processing: task #2');

上述代码因 Firefox 错误而运行错误,导致 Ember 出现问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多