等待Backbone.Collection.fetch()不等待

时间:2017-05-16 11:36:50

标签: javascript jquery backbone.js async-await es6-promise

jsfiddle

testcase.xhtml

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8" />
        <title />
        <script src="jquery-3.2.1.js"></script>
        <script src="underscore-1.8.3.js"></script>
        <script src="backbone-1.3.3.js"></script>
        <script src="testcase.js"></script>
    </head>
    <body />
</html>

testcase.js

class My_Collection extends Backbone.Collection {}
class My_View extends Backbone.View {
    async initialize() {
        let collection = new My_Collection;
        collection.url = 'http://backgridjs.com/examples/territories.json';
        console.log(collection);
        await collection.fetch();
        console.log(collection);
        $.extend(this, {collection});
        return this;
    }
    render() {
        console.log('render→→→', Date.now(), this.collection);
        this.collection.map(foo => foo);
    }
}

const view = new My_View;
view.render();

结果是

testcase.js:13:9 Object { length: 1, models: Array[1], _byId: Object, url: "http://backgridjs.com/examples/terr…" }
testcase.js:21:9 render→→→ 1494928366647 undefined
testcase.js:22:9 TypeError: this.collection is undefined
testcase.js:16:9 Object { length: 242, models: Array[242], _byId: Object, url: "http://backgridjs.com/examples/terr…" }

请注意尽管await无序执行。 Collection.fetch() is documented to return一个实现承诺的jqXHR

我希望执行等待fetch(),将集合数据附加到视图,并渲染为不会在未定义的值上崩溃。我无法看出它出了什么问题。正确的代码是什么使它按预期工作?

1 个答案:

答案 0 :(得分:3)

请注意以下事项:

async initialize() {

您使initialize异步,现在无法保证在您调用view.render(); initialize时已完成执行。您必须访问async initialize()返回的承诺,并在解决后调用render我不确定是否可能使用主干,因为即使是1.3.3来源也是如此(最新版本afaik)看起来像这样:

var View = Backbone.View = function(options) {
  this.cid = _.uniqueId('view');
  _.extend(this, _.pick(options, viewOptions));
  this._ensureElement();
  this.initialize.apply(this, arguments);
  // ^----- Does not return the promise,
  // and shouldn't because this is supposed to be a constructor
};

你会对老式的

更好
collection.fetch().then(this.render.bind(this));

为什么不使用现有的承诺?