[英]How to handle these async functions (design-pattern?)
我有一个应用程序,需要执行一些启动/启动,如:
在能够运行之前。
我现在很难以一种坚实的方式组织这些任务。 特别是异步行为让我很头疼。 目前我正在使用事件来共享提取的结果并观察应用程序的状态。 不幸的是,这导致了令人不快的垃圾。 然后我尝试使用一些承诺库,如q,jquery.defered,但它们并不真正符合我的问题。
这是代码的简化版本:
// this could be an ajax call fetching some user data
var fetchUser = function() {
var user = {};
// lets emulate the ajax call with setTimeout
setTimeout(function() {
// set some values
user.username = 'bodo';
user.password = 'helloKitty';
// return the user object we "fetched"
return user;
}, 300);
};
// this could fetch some config or some requirejs modules
var fetchConfig = function() {
var config = {};
// we emulate this too...
setTimeout(function() {
return config;
}, 200);
};
// this could be anything else like setting up some objects
var justSetUpSomething = function() {
var someObj = {};
someObj.router = 'this could be a router object for example';
someObj.logger = 'or a logger';
return someObj;
};
// in the final step everything should be merged together
// and be passed as event argument
var finalStep = function(user, config, someObj) {
var mainObj = {};
mainObj.user = user;
mainObj.config = config;
mainObj.someObj = someObj;
// trigger some event system
trigger('everything:ready', mainObj);
};
也可以在http://jsfiddle.net/uzJrs/3/查看
我希望这能描述我的问题:
有三种完全不同的异步任务。 当他们都准备好了他们的结果必须合并并以某种方式传递给另一个对象。
事件使这个可行,但远远不能理解,承诺也不会让我开心。 是不是还有另一个有用的设计模式?
首先,因为您已经有requirejs,您可以使用它来加载您的三个模块。 Requirejs异步并行地解析依赖项,并在加载时调用最终的工厂函数。
但是,每个Deferred库也提供合并promise的功能:合并后的一个会在所有单个解析时解析,或者如果其中一个被拒绝则被拒绝。 相应的函数是Q.all
和jQuery.when
:
function fetchX() {
var d = new $.Deferred();
asynchronousThing(function callback(x) {
d.resolve(x);
});
return d.promise();
}
$.when(fetchX(), fetchY(), …).then(function finalStep(x, y, …) {
// merge everything together
return new Event();
}).done(function readyCallback(e) {
// this is effectively your 'everything:ready' "event"
});
听起来你的大多数功能实际上都是同步的,只要解析了依赖关系(即config
和someObj
没有做任何异步,它们可能只是异步加载。如果你使用require.js,你试过简单地使用它的功能使用define
从代码的角度使require
调用同步?然后你只需要担心必须是异步的调用( fetchUser
)。
// In app/main.js perhaps?
define(["data/user",
"app/config",
"app/someObject",
"app/events"],
function(user, config, someObj, eventBus) {
// By the sound of it config and someObj are ready once loaded
var mainObj = {"config": config, "someObj": someObj};
eventBus.register_once("data:user:loaded", function(user) {
mainObj.user = user;
eventBus.trigger("everything:ready", mainObj);
});
user.fetchUser()
});
// in data/user.js
define(["app/config", "app/events", "vendor/jquery"],
function(config, eventBus, $) {
function user_loaded(user) {
eventBus.trigger("data:user:loaded", user);
}
function fetchUser() {
$.get(config.dataendpoint + "/user/1", user_loaded);
}
return {"fetchUser": fetchUser};
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.