Appcelerator 和 CommonJS 模块(缓存和循环引用) [英] Appcelerator and CommonJS modules (caching and circular references)

查看:25
本文介绍了Appcelerator 和 CommonJS 模块(缓存和循环引用)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

事情是这样的:

我正在使用 CommonJS 方法使我的移动 (iPhone/Android) 应用程序模块化.不出意外.但是有一件事我就是想不通.

CommonJS 让我可以创建 STATIC 私有变量,这让我可以轻松地创建单例.至少,我认为这是因为获取 require()d 的文件的内容只读取一次,然后每次都返回导出对象(仅初始化一次).

但是当我创建如下所示的循环引用时,每次都会执行包含模块中的代码.

等等...有趣的是,在我写这个问题的时候,我突然意识到对 require() 的所有调用都没有在下一个调用开始之前完成(因此堆栈溢出如下所示).

对我是否走上正轨有什么想法吗?这里已经过了凌晨 5 点,所以就我而言,所有的赌注都已取消 :D.

示例:

看这段代码,它定义了一个单例:

/* Singleton.js */出口.getSingleton = getSingleton;函数 getSingleton(name) {如果(!实例){实例 = 新事物(名称);}返回实例;}功能事物(名称){this.name = 名称;}var 实例;

require()这个文件是这样的:

var theFirstThing = require('Singleton').getSingleton('first');Ti.API.info('first:' + theFirstThing.name)var possibleAnotherOtherThing = require('Singleton').getSingleton('second');Ti.API.info('second: ' + possibleAnotherOtherThing.name);

输出是:

[DEBUG] 加载:/path/to/sim/MyApp.app/app.js,资源:app_js[DEBUG] 加载:/path/to/sim/MyApp.app/Singleton.js,资源:Singleton_js[INFO] 第一:第一[INFO] 第二:第一

为什么像下面这样的循环引用不起作用?(我自己可能已经对此进行了分析,如果您愿意,可以评论/回答).

app.js

require('香蕉');

Pinapple.js

require('香蕉');

Banana.js

require('菠萝');

因为输出是这样的:

[DEBUG] 加载:/path/to/simulator/MyApp.app/app.js,资源:app_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Banana.js,资源:Banana_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Pineapple.js,资源:Pineapple_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Banana.js,资源:Banana_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Pineapple.js,资源:Pineapple_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Banana.js,资源:Banana_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Pineapple.js,资源:Pineapple_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Banana.js,资源:Banana_js/* 等等(总共来回 15 次)*/[DEBUG] 加载:/path/to/simulator/MyApp.app/Pineapple.js,资源:Pineapple_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Banana.js,资源:Banana_js[DEBUG] 加载:/path/to/simulator/MyApp.app/Pineapple.js,资源:Pineapple_js[错误] 脚本错误 = 超出最大调用堆栈大小.(未知文件)

解决方案

我也在 Appcelerator Titanium 中使用 CommonJS 模块来构建移动应用程序.我为解决循环依赖问题所做的是:如果 A 和 B 是 2 个循环依赖模块,则在 B 中需要 (A),反之亦然 就在您实际需要使用它之前.在我的例子中,只有当某个按钮被点击时,我才需要在 B 中使用 A,所以我在按钮的点击事件侦听器中的 B 中放置了一个 require(A).希望有所帮助.

Here's the thing:

I'm using the CommonJS way of making my mobile (iPhone/Android) application modular. No surprise there. But there's one thing that I just can't get my head around.

CommonJS lets me create STATIC private variables, which lets me create singletons at ease. This, I think at least, is because the contents of a file that gets require()d is read only once and then the exports object (which is initialized only once) is returned every time.

But when I create a circular reference as seen below, the code inside the included module is executed every time.

Wait... Funny thing is, while I'm writing this question, I suddenly realise that none of the calls to require() finish before the next one starts (hence the stack overflow demonstrated below).

Any thoughts on whether I'm on track or not? It's past 5 AM over here, so all bets are off as far as I'm concerned :D.

EXAMPLES:

See this piece of code, it defines a singleton:

/* Singleton.js */

exports.getSingleton = getSingleton;

function getSingleton(name) {
  if (!instance) {
    instance = new Thing(name);
  }

  return instance;
}

function Thing(name) {
  this.name = name;
}

var instance;

I require() this file as such:

var theFirstThing = require('Singleton').getSingleton('first');
Ti.API.info('first: ' + theFirstThing.name)

var possiblyAnotherOtherThing = require('Singleton').getSingleton('second');
Ti.API.info('second: ' + possiblyAnotherOtherThing.name);

The Output is:

[DEBUG] loading: /path/to/sim/MyApp.app/app.js, resource: app_js
[DEBUG] loading: /path/to/sim/MyApp.app/Singleton.js, resource: Singleton_js
[INFO] first: first
[INFO] second: first

Why is it then that circular references like the following don't work? (I might have already ansered this myself, comment/answer on it if you like).

app.js

require('Banana');

Pinapple.js

require('Banana');

Banana.js

require('Pineapple');

Because the output is this:

[DEBUG] loading: /path/to/simulator/MyApp.app/app.js, resource: app_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js

/* etcetera (total of 15 times back and forth) */

[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[ERROR] Script Error = Maximum call stack size exceeded. (unknown file)

解决方案

I too am using CommonJS modules in Appcelerator Titanium to build a mobile app. What I did to resolve the circular dependency problem was this: if A and B are the 2 circularly-dependent modules, require(A) in B, and vice-versa just before you actually need to use it. In my case, I needed A inside B only when a certain button got clicked, so I put a require(A) in B inside the button's click event listener. Hope that helps.

这篇关于Appcelerator 和 CommonJS 模块(缓存和循环引用)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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