window.alert 模型回调后执行的 willTransition 回调中的代码
code in willTransition callback executed after model callback after a window.alert
我最近遇到了 Ember.js 的错误。基本上,当我在 Firefox 中单击浏览器后退按钮时,Ember.js 以错误的顺序执行代码。 alert("...");
行后 willTransition
回调中的代码在 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 错误。
此错误如何导致相关行为
引擎盖下发生了什么
- 用户点击浏览器后退按钮后,URL发生变化,浏览器历史记录发生变化,触发
PopStateEvent
,然后Ember用[=处理这个事件15=]回调
- 作为回调,Ember 通过调用
this._doURLTransition('handleURL', url);
开始转换
- 在转换内部,创建了一个 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 行为。
我最近遇到了 Ember.js 的错误。基本上,当我在 Firefox 中单击浏览器后退按钮时,Ember.js 以错误的顺序执行代码。 alert("...");
行后 willTransition
回调中的代码在 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 错误。
此错误如何导致相关行为
引擎盖下发生了什么
- 用户点击浏览器后退按钮后,URL发生变化,浏览器历史记录发生变化,触发
PopStateEvent
,然后Ember用[=处理这个事件15=]回调 - 作为回调,Ember 通过调用
this._doURLTransition('handleURL', url);
开始转换
- 在转换内部,创建了一个 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 行为。