javascript - 异步加载模块属性

标签 javascript requirejs amd ractivejs

我定义了一个模块(module1),它应该异步加载属性的值。如何在定义后立即在我的应用程序中使用此属性?

我的设置(简化)

v1

app.js

require(['module1'], function(mod) {
    document.getElementById("greeting").value = mod.getPersonName();
});

module1.js

define(['jquery'], function($) {
    _person;

    $.get('values/person.json')
        .done(function(data) {
            _person = data
        });

    return {
        getPersonName: function() { return _person.name; }
    }

values/person.json

{ name: 'John Doe', age: 34 }    

这仅在 GET 几乎瞬时发生时才有效,否则会失败,因为调用 getPersonName 时 _person 未定义。

v2

为了解决这个问题,我想我应该注册一个回调来在加载人员时通知应用程序。

app.js

require(['module1'], function(mod) {
    mod.onPersonLoaded(function() {
        document.getElementById("greeting").value = mod.getPersonName();
    });
});

module1.js

define(['jquery'], function($) {
    _person;
    _onLoaded;

    $.get('values/person.json')
        .done(function(data) {
            _person = data;
            _onLoaded();
        });

    return {
        getPersonName: function() { return _person.name; },
        onPersonLoaded: function(cb) { _onLoaded = cb; }
    }
}

如果 GET 速度较慢,则此方法有效,但如果速度较快,则在调用 .done() 时 _onLoaded 未定义。

有没有一种好方法可以在 app.js 中一旦定义并仅在定义后使用 _person 值?

我正在使用 RequireJS,但我的问题通常适用于 AMD。

编辑

在简化我的示例时,我删除了一个可能很重要的层。我使用 RactiveJS 作为 UI。

设置(稍微简化)

app.js

require(['Ractive', 'module1'], function(Ractive, mod) {

    var ractive = new Ractive({
        ...
        data : {
            name: mod.getPersonName()
        }
    });

    ractive.observe(...);
    ractive.on(...);

});

编辑2

我当前的解决方案,可能会发生变化。注册一个回调,在加载 person 时通知 app.js。注册回调时,如果人员已经加载,则立即调用回调。

app.js

require(['Ractive', 'module1'], function(Ractive, mod) {

    var ractive = new Ractive({
        ...
        data : {}
    });

    mod.watchPerson(function() {
        ractive.set('person.name', mod.getPersonName());
    });

    ractive.observe(...);
    ractive.on(...);

});

module1.js

define(['jquery'], function($) {
    _person;
    _onLoaded;

    $.get('values/person.json')
        .done(function(data) {
            _person = data;
            try {
                _onLoaded();
            } catch (e) {
                // that was fast!
                // callback will be called when it is registered
        });

    return {
        getPersonName: function() { return _person.name; },
        watchPerson: function(cb) { 
            _onLoaded = cb;
            if(_person != null) {
                _onLoaded();
            }
        }
    }
}

最佳答案

Promise 在这里是一个不错的选择,因为回调总是异步调用 - 您永远不会遇到 _onLoaded() 在设计之前就被调用的困惑情况。

不幸的是,jQuery 的 Promise 实现并不遵守 Promises/A+ specification ,所以你得不到这个保证。如果可能,您可以使用替代 AJAX 库,例如 Reqwest ,然后做类似的事情

app.js

define(['module1'], function (mod) {
  mod.then(function(person) {
    // do something with person.name
  }
});

module1.js

define(['reqwest'], function (reqwest) {
  return reqwest('values/person.json');
});

使用文本加载器插件

由于您已经在使用 AMD,另一个选择是使用加载器插件,例如 text :

app.js

define(['module1'], function (person) {
  // do something with person.name
});

module1.js

define(['text!values/person.json'], function (personJSON) {
  return JSON.parse(personJSON);
});

使用文本加载器插件

事实上甚至还有一个JSON plugin ,因此在此示例情况下您可以完全取消 module1:

app.js

define(['json!values/person'], function (person) {
  // do something with person.name
});

关于javascript - 异步加载模块属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21390684/

相关文章:

javascript - 将 requirejs 与 Node 一起使用

javascript - RequireJS'ing 一个没有全局 $ 变量的 jQuery 插件

javascript - JavaScript 是否有类似 CDI 的机制

javascript - 不支持 ES6 扩展语法 IE

javascript - 水平展开而不是垂直展开

javascript - 所有 .js 文件都以看似随机的十六进制字符开头

typescript - 使用 SystemJS 和 TypeScript 从捆绑文件中执行模块

javascript - 在 Woocommerce 中交换图像变化的问题

javascript - 将 Select2 数组输出转换为字符串

javascript - 带有 requirejs 和许多路径别名和包的 gulp-typescript,错误 TS2307