使用糖语法动态加载requirejs模块 [英] Loading requirejs modules Dynamically with sugar syntax

查看:139
本文介绍了使用糖语法动态加载requirejs模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好我正在尝试以动态方式加载一些requireJs模块,方法是获取一个过滤器列表和遍历数组的迭代来加载这样的模块

Hi i am trying to load some requireJs modules in a dynamic way by getting a list of filters and the iterate over the array to load this modules like this

define(function(require){
var runFilters = function(filters){
    var _ = require('underscore');
    var computedFilters  = getFilters(filters);
    var result = _.every(computedFilters,function(filter){
        return filter();
    });
    return result;
};

var getFilters = function(filters){
    var _ = require('underscore');
    return _.map(filters,function(filter){
        return require('filters/' + filter);
    },this);
}


var register = function(filters,fn){
    return function(){
        var args = Array.prototype.slice.apply(arguments);
        if(runFilters(filters))
            fn.apply(this,args);
    }
}
return{
    register: register
}
});

这给我发错误:未捕获错误:模块名称filters / isAuth尚未加载上下文:_

This give me error: Uncaught Error: Module name "filters/isAuth" has not been loaded yet for context: _

但是当将其替换为静态方式(仅用于测试)时,它会完全加载

but when replacing this to a static way (just to test) it loads perfectly

define(function(require){
    var runFilters = function(computedFilters){
        var result = _.every(computedFilters,function(filter){
            return filter();
        });
        return result;
    };

    var getFilters = function(filters){
        var _ = require('underscore');
        return _.map(filters,function(filter){
            console.log(filter);
            return require('filters/' + filter);
        },this);
    }


    var register = function(filters,fn){
        var cachedFilters = [];
        cachedFilters.push(require('filters/isAuth'));
        return function(){
            var args = Array.prototype.slice.apply(arguments);
            if(runFilters(cachedFilters))
                fn.apply(this,args);
        }
    }
    return{
        register: register
    }
});

这也给我错误

cachedFilters.push(require('filters'+'/isAdmin'));


推荐答案

你遇到了RequireJS支持的限制CommonJS语法。这是交易。当RequireJS定义一个模块时,它会查看你给 define 的工厂函数(回调)。它寻找这种模式:

You've run into a limitation of RequireJS's support for the CommonJS syntax. Here's the deal. When RequireJS defines a module, it looks at the factory function (the callback) you gave to define. It looks for this pattern:

/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g

这匹配 require 调用,如 var foo = require('foo'); For每个这样的调用,它将所需的模块添加到模块的依赖项列表中。例如,如下所示:

This matches require calls like var foo = require('foo'); For each such call, it adds the required module to the list of dependencies of your module. So, for instance, something like:

// The `require` parameter must be present and is filled with something useful
// by RequireJS.
define(function (require) {
    var foo = require('foo');
    var bar = require('bar');
    ...
});

这样对待:

define(['require', 'foo', 'bar'], function (require) {
    var foo = require('foo');
    var bar = require('bar');
    ...
});

如果仔细查看上面的正则表达式,你会发现看到它只匹配 require 具有参数的调用,该参数是文字字符串。因此 require(something+ somevar)之类的东西将无效。在进行此转换时,RequireJS完全忽略它们。

If you look carefully at the regular expression above, you'll see it will match only require calls that have a single parameter which is a literal string. So things like require("something" + somevar) won't work. RequireJS completely ignores them when doing this transformation.

通过更改正则表达式无法修复此问题。 RequireJS的核心是一个用于异步加载模块的系统。使用单个字符串文字的 require 调用的形式是糖,以允许更容易移植根据CommonJS模式设计的模块,以及喜欢这种风格的人(即使他们没有搬运任何东西)。这种类型的调用看起来是同步的,实际上并不是同步为了支持计算传递给它的名称的情况,RequireJS必须预测该值是什么。

The issue would not be fixable by changing the regular expression. RequireJS is at its heart a system for loading modules asynchronously. The form of the require call with a single string literal is sugar to allow porting more easily modules designed according to the CommonJS pattern, and for those who prefer this style (even if they are not porting anything). This type of call looks synchronous without actually being synchronous. To support cases where the name passed to it is computed, RequireJS would have to predict what the value would be.

如果你想完全自由地加载任何模块你想要在你的代码中提前知道名称可能是什么,那么你必须使用异步 require 调用( require([computed_value], function(mod){...}))这意味着你的代码必须是异步的。如果您要加载一组有限的模块,总是可以加载所有模块,那么您可以使用文字字符串全部要求它们:

If you want to have complete freedom to load whatever module you want in your code without knowing ahead of time what the name may be, then you have to use an asynchronous require call (require([computed_value], function(mod) {...})) which means your code must be asynchronous. If you have a limited set of modules you want to load and it is acceptable to always load them all, then you could require them all with literal strings:

define(function (require) {
    require("filters/isAdmin");
    require("filters/b");
    require("filters/c");
    require("filters/d");
    ...
});

RequireJS将进行上述转换并进一步 require 使用解析为模块中早期所需名称之一的计算值的调用不会失败。

RequireJS would do the transformation above and further require calls using computed values that resolve to one of the names you required early in your module would not fail.

这篇关于使用糖语法动态加载requirejs模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆