Backbone:TypeError:无法调用undefined方法'apply'

时间:2015-08-02 13:41:03

标签: node.js backbone.js

我正在尝试将json文件加载到Backbone Collection中,但我一直遇到“TypeError:无法调用方法'应用'未定义”错误。

具体做法是:

return Backbone.$.ajax.apply(Backbone.$, arguments);
TypeError: Cannot call method 'apply' of undefined

这是我的剧本:

var Backbone = require('backbone');
var PostModel = Backbone.Model.extend();
var PostCollection = Backbone.Collection.extend({
    model: PostModel,
    url: "data.json", 
    parse: function(data) {
    return JSON.parse(data);
    }
});

var posts = new PostCollection();
posts.fetch({reset: true});
posts.bind('reset', function () { console.log(posts); });

是不是因为异步?我该如何解决这个问题?

3 个答案:

答案 0 :(得分:0)

如果您在nodejs环境中运行代码而不是浏览器,那么您可以使用najax模块发出请求

var Backbone = require('backbone'),
    najax = require('najax');

// set alias to najax
Backbone.ajax = najax;

var PostModel = Backbone.Model.extend();
var PostCollection = Backbone.Collection.extend({
    model: PostModel,
    url: "data.json", 
    parse: function(data) {
       return JSON.parse(data);
    }
});

var posts = new PostCollection();
posts.fetch({reset: true});
posts.bind('reset', function () { console.log(posts); });

修改

如果您的data.json文件位于同一文件夹中,就像您在评论中指出的那样,那么您就不需要使用urlfetch。您需要先获取数据,然后使用它们初始化您的数据:

var Backbone = require('backbone'),
    data = require('./data.json');

var PostModel = Backbone.Model.extend();
var PostCollection = Backbone.Collection.extend({
    model: PostModel,
    parse: function(data) {
       return JSON.parse(data);
    }
});

var posts = new PostCollection(data, {parse: true});

答案 1 :(得分:0)

基本问题是Backbone.$.ajaxundefined,因此您无法使用apply()

调用它

在没有看到更多代码的情况下,我无法确定为什么会这样,但我的猜测是你正在使用像Browserify或Webpack这样的东西。

直到我认为,最新版本的Backbone,Backbone。$并没有在commonJS(例如Node)环境中自动引用jQuery或Zepto - 你必须手动附加它。确保安装了jQuery,然后尝试:

var Backbone = require('backbone')
var $ = require('jQuery');
Backbone.$ = $;
return Backbone.$.ajax.apply(Backbone.$, arguments);

答案 2 :(得分:0)

今天我遇到同样的问题,试图测试jQuery&使用npm test文件的主干。

问题: jQuery.ajax()方法不是静态函数。因此,在编译时,在jQuery的1.x和2.x版本中都不存在这些:function ajax()this.ajax: function().ajax()方法是在初始化时动态构建的。它是在jQuery加载到DOM时创建的,但是没有DOM就不可用。由于您运行Node.js,您必须模拟假DOM(全局文档和窗口对象),然后将窗口对象传递给jQuery以创建$ .ajax方法。然后你可以将它映射到Backbone的ajax方法以使其工作。还需要全局文档对象来允许jQuery初始化。

这是创建动态$.ajax()方法的jQuery代码。我只是指出它,以便你可以看到它是在这段代码中动态构建的:

jQuery.each( [ "get", "post" ], function( i, method ) {
    jQuery[ method ] = function( url, data, callback, type ) {

        // shift arguments if data argument was omitted
        if ( jQuery.isFunction( data ) ) {
            type = type || callback;
            callback = data;
            data = undefined;
        }

        // The url can be an options object (which then must have .url)
        return jQuery.ajax( jQuery.extend( {
            url: url,
            type: method,
            dataType: type,
            data: data,
            success: callback
        }, jQuery.isPlainObject( url ) && url ) );
    };
} );


jQuery._evalUrl = function( url ) {
    return jQuery.ajax( {
        url: url,

        // Make this explicit, since user can override this through ajaxSetup (#11264)
        type: "GET",
        dataType: "script",
        cache: true,
        async: false,
        global: false, // <- This 1.x line is removed from 2.x
        "throws": true
    } );
};

原因: jQuery的未分析版本,在文件顶部提到以下内容:

// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var jQuery = require("jquery")(window);
// See ticket #14549 for more info.

我在此NPM链接中找到了相同的代码,但我很难让他们的模拟DOM代码工作:https://www.npmjs.com/package/jquery#node

解决方案:要修复您的代码,您可能需要添加此代码,该代码通过以下网址拼凑在一起:https://github.com/tmpvar/jsdom#how-it-works

var jsdom = require("jsdom").jsdom;

var markup = "<html><body></body></html>"; // Creates a default DOM.
var options = {}; // See: https://github.com/tmpvar/jsdom#how-it-works

global.document = jsdom(markup, options); // Creates a document object from Node.
global.window = global.document.defaultView; // Creates a window object from Node.

// Passes the window object into jQuery, so that it can create the .ajax() method:
const $ = require("jquery")(global.window) 

// This maps the dynamic .ajax method into Backbone:
Backbone.$.ajax = $.ajax; 

那应该修复你的Node.js代码&amp; NPM测试,你会很开心! : - )