Browserify 需要返回一个空对象

Posted

技术标签:

【中文标题】Browserify 需要返回一个空对象【英文标题】:Browserify require returns an empty object 【发布时间】:2014-12-14 06:22:11 【问题描述】:

我有这段代码,由于我无法理解的原因,在使用require() 时会产生一个空对象。我的文件结构是这样的:

src
|__ public
    |__ javascript
        |__ collections
            |   categories.js
            |   listings.js <-- Always an empty object
        |__ models
            |   category.js
            |   employer.js
            |   listing.js
            |   location.js
        |   routing
        |   templates
        |   tests
        |   ui-components
        |   views

问题文件是collections/listings.js,它似乎在需要时简单地输出为一个空对象,如下所示:

var ListingsCollection = require('../collections/listings')

src/public/javascript/collections/listings.js 看起来像这样:

var $        = require('jquery'),
    _        = require('underscore'),
    Backbone = require('backbone'),
    Listing  = require('../models/listing');

Backbone.$ = $;

module.exports = Backbone.Collection.extend(
    url: '/listings',

    model: Listing,

    parse: function (response) 
        return response.listings;
    
);

这是一个出错的例子:

var $                  = require('jquery'),
    _                  = require('underscore'),
    Backbone           = require('backbone'),
    LocationModel      = require('../models/location'),
    ListingsCollection = require('../collections/listings');

Backbone.$ = $;

console.log(ListingsCollection); // > Object 

module.exports = Backbone.Model.extend(

    urlRoot: '/employers',

    model: 
        location: LocationModel,
        listings: ListingsCollection
    ,

    parse: function (response) 
        var employer = response.employer;

        // Create the child listings
        employer.listings = new ListingsCollection;

        return employer;
    ,

    toJSON : function () 
        var json = _.clone(this.attributes);

        _.each(_.keys(this.model), function (child) 
            if (this.get(child)) 
                json[child] = this.get(child).toJSON();
            
        .bind(this));

        return json;
    
);

就是这样 - 该集合永远不需要雇主模型,因此它可以用于为父模型创建子集合。我已经查看了源代码并研究了这个问题,但到目前为止我什么都没有想出......这很令人困惑。

【问题讨论】:

控制台有错误吗? 最后能和.js一起工作吗? @machineghost - 当我尝试将空对象用作预期的 Collection 对象时,会出现控制台错误。 browserify 捆绑过程运行顺利。 requirejs.org/docs/api.html#circular 这只是 Require 的“乐趣”的一部分:你不能让模块 A 导入 B 导入 A(或 B 导入 C 导入 A,或......)。希望它不需要太多修改;我发布的那个链接有一些提示。 【参考方案1】:

由于我的评论似乎已经回答了这个问题,所以我想我会正式写出来。

使用 Require.js 时,您必须考虑模块之间的依赖关系。从某种意义上说,这与您不使用 require 时的问题相同。假设你有两个文件,A.js 和 B.js,分别定义了一个“A”函数和一个“B”函数:

// A.js
window.A = function() 
    // ...
;

// B.js
window.B = function() 
    // ...
;

您可以按任意顺序将这些文件添加到您的页面,您的代码将正常工作。但是如果你对“B”的定义依赖于“A”的定义呢:

// B.js
window.B = window.A || function() 
    // ...
;

现在,顺序很重要:您必须在 A.js 文件之后包含 B.js 文件,否则 B 的代码将无法工作。如果你的 A.js 也依赖于你的 B.js ...

// A.js
window.A = window.B || function() 
    // ...
;

那么你的代码有致命的缺陷,因为 B 依赖于 A 而 A 依赖于 B,并且必须首先定义一个。这就是所谓的“循环依赖”。

Require 也有同样的问题,只是它更容易被忽略,因为 Require 从你那里抽象了很多东西。尽管 Require(作为 JavaScript 代码)最终必须按顺序运行,这意味着它必须以某种顺序定义您的模块。如果您的模块 A 依赖于模块 B,而 B 依赖于 A,那么您将遇到相同的循环依赖问题。

类似地,如果 A 依赖于 B,B 依赖于 C,C 依赖于 A,你也会有循环依赖。或者,如果你有一个依赖于 D 的 C,那么你明白了。最终,依赖于任何其他模块的任何模块都必须确保依赖模块或其任何依赖项都不依赖于原始模块。

那么你如何修复你的代码呢?显而易见的方法是删除循环依赖,这肯定会起作用,但还有另一种选择。假设您的 A 依赖于 B,但仅在 运行时,而不是在 加载时。换句话说,而不是:

// A.js
define(['B'], function(B) 
    return B || function() 
        // ...
    ;
);

你有:

// A.js
define(['B'], function(B) 
    return function() 
        B();
    ;
);

在这种情况下,您可以使用单参数“同步”形式的 require,以避免在文件顶部使用“B”:

// A.js
define([], function() 
    return function() 
        var B = require('B');
        B();
    ;
);

因为我们只在之后使用了B,所以我们已经定义了我们所有的模块Require不必担心A在B之后;它可以随时定义它,因为当您真正想要使用 B 时,它已经被定义了。当然,这假设您有 some 模块,该模块实际上确实在顶部包含“B”(如果您不要求甚至不知道 B 存在)。

希望对您有所帮助。

【讨论】:

感谢机器鬼。当我问这个问题时,你阻止了我陷入困境,我最终重新考虑了我的代码结构以避免这个问题。不用说它节省了很多时间。

以上是关于Browserify 需要返回一个空对象的主要内容,如果未能解决你的问题,请参考以下文章

使用 Node.JS、Express 和 EJS 实现 browserify 的示例

在browserify中需要彼此的两个文件[重复]

Webpack 怎么用

req.body 返回一个空对象 // 输出

PHP laravel 返回空对象 {}

selenium的一些操作