简体   繁体   中英

how do I use curl.js to load an object?

Curl 0.7.3

I got some AMD/CommonJS adapter code from here: supporting both CommonJS and AMD

(function (name, definition) {
      if (typeof module != 'undefined') {
        module.exports = definition();
      }
      else if (typeof define == 'function' && typeof define.amd == 'object') {
        define(name, [], definition);
      }
      else {
        this[name] = definition();
      }
    }('modXyz', {
          sayHi:function (name) {
            console.log('Hi ' + name + '!');
          }
        }
    ));

I'd like to use that code with Curl to make all my code AMD/CommonJS compatible. What I was expecting to be able to do was this:

greeter = curl(['modXyz']); 
greeter.sayHi("Gracie"); 

But the object that curl returns isn't the object I'm expecting. The closest I can get is this:

curl(['modXyz'], function(mod) { window.greeter = mod; }); 
greeter.sayHi("Gracie");

Which seems to defeat the purpose of AMD. Is curl capable of doing something like this? Do I have to use require.js to get it to happen?

CurlJS and RequireJS both support the AMD AND CommonJS require call patterns:

The difference between CJS and AMD is the use of Array as wrapper for the list of dependencies. Also note that in CurlJS's config you can alias curl to require to make your code fully compatible with AMD spec. Observe:

CJS require call pattern:

var a = require('name')

ONLY CurlJS AMD require call pattern:

var promise = require(['name'])
promise.then(callbackFunction)

This commonly can be shortened to:

require(['name']).then(callbackFunction)

Note, CurlJS's returning of a Promise object is NOT part of the AMD spec. The AMD spec does not seem to prescribe a return value for AMD-style require call.

Both, RequireJS and CurlJS support standard AMD require call patterns:

require(['name'], callbackFunction)

Again, note the use of Array as a flag that this is an AMD style require. That triggers different logic for return value.

To make your thing work as you want, on CurlJS, your code must be inside a module that is wrapped as if it's a CommonJS module, use:

define(function(require) { ... });

I am told that in that case, the require you get behaves like CommonJS style require - sync. In reality, what happens behind the scenes is the loader scans the factory function for things you require and folds them into list of requirements for that define. Then, inside the factory you can do:

var greeter = require('modXyz'); 
greeter.sayHi("Gracie");

Note, the "sync" behavior is still an illusion, as what actually happens is that detected required resources are preloaded.

On RequireJS even global require can be called CJS style: var resource = require('resource/path') , but only after you have already loaded it before.

In other words, the loading always happens async in both CurlJS and RequireJS before the factory function runs, but in RequireJS you can use that almost everywhere, while in CurlJS it's very very niche scenario.

Because the browser is remote from its resources, it has to either block the main thread while it fetches those resources or it has to fetch them asynchronously. Since we should never block the main thread (effectively making the browser unresponsive), we have to fetch resources async. (It's the same with any AMD loader, RequireJS, dojo, etc.)

Therefore, things like the following just can't work:

var foo = require('lib/foo');

Well, it can't work in the usual global-ish space you may be used to in browsers. It can , however, work in a controlled environment such as inside an AMD module.

Step 1: write your code inside of modules.

Step 2: write a bootstrap module to launch your app.

<script src="lib/curl/src/curl.js"><script>
<script src="myapp/run.js"><script>

Inside run.js:

// curl 0.7.x requires a named module here ('myapp/run')
define('myapp/run', ['curl'], function (curl) {
    curl.config(
        baseUrl: '',
        packages: [ /* configure your 3rd-party packages */ ],
        paths: { /* configure any non-package 3rd-party libs here */ },
        preloads: [ /* put modules that *must* be loaded first here (e.g. shims) */ ],
        main: 'myapp/main'
    });
});

"myapp/main" could then look something like this:

define(function (require) {
    var view1 = require('myapp/view1/controller');
    view1.render();
    view1.placeAt('body');
});

Inside the main module (or any AMD module), the require acts more like I think you're expecting. Note that this is a special AMD signature. You can't specify dependencies in the define and expect the require to behave like this. You have to specify your dependencies in only one way. This will not work:

define(['myapp/view1'], function (view1) {
    var foo = require('foo');
});

Hope this helps.

-- John

the curl function is asynchronous, and returns a promise. So you can only get the result either as a callback you pass to curl, or with a callback you pass to then (called once the promise has been fulfilled.

curl(['dep1', 'dep2', 'dep3' /* etc */], callback);

or

curl(['dep1', 'dep2', 'dep3' /* etc */])
    .then(callback, errorback);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM