未捕获的错误:断言失败:在已销毁的对象上调用set方法。

43

我在ember-cli测试中工作。当所有测试都通过时,它会返回额外的两个具有错误的测试。

未捕获的错误:断言失败:在已销毁的对象上调用set 来源: '../dist/assets/vendor.js:13269'

这是一个单元测试配置。

import Ember from "ember";
import { test,moduleFor } from 'ember-qunit';
import startApp from '../helpers/start-app';

var App;

module('An Integration test',{
    setup:function(){
        App=startApp();
    },
    teardown: function() {
        Ember.run(App, 'destroy');
    }
});

你解决这个问题了吗? - Shagymoe
对我来说,在销毁对象之前,我必须使用 async/wait 来读取它。 - Rami Alloush
4个回答

52

出现这种情况可能是因为在承诺或其他延迟的代码中,您没有检查对象的销毁状态,或者是因为您没有清除已设置并与DOM事件或Ember核心之外的任何东西进行交互的内容。

我曾经在一些映射到Ember的jQuery插件上遇到过这个问题,在测试期间,插件销毁得太慢,然后我要么没有使用运行循环,要么没有检查我正在操作的Ember对象的销毁状态。

您可以通过以下方式进行检查:

if ( !(obj.get('isDestroyed') || obj.get('isDestroying')) ) {
  // do your destroying code setting stuff
}

还要考虑销毁在视图代码中初始化的任何jQuery插件(例如,在didInsertElement中设置的所有内容都应该在willDestroyElement中拆除)。


你说的"// do you destroying code setting stuff"是什么意思?我也遇到了同样的问题,我在调用一些代码:this.$(document).on('click', '.myEl', function() { // do something });。我注意到当用户导航到不同的路由并返回到具有上述代码的路由时,此点击处理程序不起作用。请注意,点击处理程序位于视图内部。 - JackH
你不应该监听那样的事件。如果点击事件与视图相关,则必须使用视图的eventManager属性(请参见http://emberjs.com/api/classes/Ember.View.html#toc_event-managers)。无论如何,您可能已经监听了一些jQuery事件并尝试调用一些Ember对象的方法(包括get/set)。如果是这样,请确保在`willDestroyElement`中删除事件侦听器,如果您无法删除,请将事件函数的主体用我写的这个`if`语句包围起来,以便在Ember对象已经被销毁或正在销毁的情况下,您将不会遇到错误。 - Huafu
我已经将我的jQuery选择器包含在你分享的if语句中。我只是用Ember对象中的“this”替换了obj。这样做对吗?我仍然看到错误。 - JackH
2
@Nagarjun 我会将链接的答案作为另一个答案添加到这个问题中。 - givanse
2
未来的旅行者:如果您想在整个Ember应用程序中避免这个问题,可以探索http://ember-concurrency.com/,这是一种强大的方法。 - Sam Selikoff

15

我曾经也遇到过类似的问题。当你在一个 Promise 中有 "this.set()" 时,有可能 Promise 花费的时间太长以至于用户已经离开了那个页面,在这种情况下,你试图设置的东西已经被销毁了。我发现最简单的解决方案就是在 Promise 开始时进行简单的检查。

if (this.isDestroyed) {
    return;
}
this.set('...');
...

编辑:或者您可以使用Ember.trySet


嗨,你为这个做了什么? - Karthiga

2
这个问题与一个承诺没有完全解决并且紧接着运行另一个测试有关。
你应该尝试使用Ember Concurrency
导入 { task, timeout } from 'ember-concurrency';
myFunction: task(function * () {

  // do somethinng

  yield timeout(1000); // wait for x milliseconds

  // do something else

}).drop(),

0

在一次集成测试中,我遇到了类似的问题。为解决该问题,在集成测试中,我等待执行下一个操作。

import wait from 'ember-test-helpers/wait';
wait().then(() => {
// perform action (which previously used to cause an exception)
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接