我正在尝试将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); });
是不是因为异步?我该如何解决这个问题?
答案 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
文件位于同一文件夹中,就像您在评论中指出的那样,那么您就不需要使用url
和fetch
。您需要先获取数据,然后使用它们初始化您的数据:
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.$.ajax
为undefined
,因此您无法使用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测试,你会很开心! : - )