RequireJS 的 require 调用什么时候是异步的?什么时候同步?

When is RequireJS' require call asynchronous? When is it synchronous?

我使用 RequireJS 在我的一个项目中加载我的模块。 我在网络上看到使用 require 调用(而不是 define)来请求模块的不同方式。

假设我有一个名为 "JQuery" 的模块并且我想要使用它。 正如我在示例中看到的,有两种可能的方法:

  1. 这个:

    require(["JQuery"], function($){
       $.doSomething();
    })
    
  2. 还有这个:

    var $ = require("JQuery");
    $.doSomething();
    

我的问题是,如果负载像 RequireJS 文档所说的那样是异步的,那么第二个约定如何工作?我如何确定 $ 已定义并且第一行在第二行执行之前完成?

根据 require.js 文档,它是一个包装器。所以它正在重建代码以异步工作。它被称为 CommonJs 包装器。您可以找到有关它的更多信息 here

我不知道 requirejs。但我认为可以用 syncasync 两种方式加载模块。

function require(name,cb){
    if(cb !== undefined){
        requireAsync(name,cb);
    }else{
        requireSync(name);
    }
}

RequireJS 总是异步加载模块,但它允许一种看起来同步的 require 形式。您的第二个代码段实际上缺少一些非常重要的代码。 (此外,jQuery 的模块名称被硬编码为 jquery。您可以编写一个允许您将其称为 jQuery 的配置,但没有意义。)这种形式的 require 调用被设计为在模块内部使用所以:

define(function (require) {
    var $ = require("jquery");
    $.doSomething();
});

RequireJS 对上面的代码所做的是在执行之前将其转换为:

define(['jquery'], function (require) {
    var $ = require("jquery");
    $.doSomething();
});

注意添加依赖项作为 define 的第一个参数。当 RequireJS 执行代码时,它会找到依赖项,加载 jquery 然后调用匿名函数。遇到 require("jquery") 时,模块已经加载。 归根结底,虽然 require 调用 看起来 是同步的,但它所需的模块加载仍然是异步发生的。

能否在 define 调用之外使用这种同步形式 require?仅当您可以接受失败时。 如果传递给它的模块尚未加载,这个 require 调用将失败。 你会得到臭名昭著的错误:

Module name ... has not been loaded yet for context: ...

像我上面展示的那样在 define 中使用它是安全的。或者我想你可以这样做:

require(['jquery'], function (require) {
    var $ = require("jquery");
    $.doSomething();
});

哪个 起作用,但是手动重复依赖关系有什么意义。 (如果您想知道,RequireJS 不会 转换带有回调的 require 调用,就像我在此处示例中使用的回调一样,它转换 define 如上所示调用。)