JavaScript - 使用包含异步回调但仍返回原始值的函数覆盖函数
JavaScript - override a function with a function that contains async callbacks and still return original value
在JavaScript中,我想覆盖对象上的函数,但仍然调用原始函数并返回其值。所以我通常会做这样的事情:
var render = res.render;
res.render = function() {
doSomethingNew();
return render.apply(this, arguments);
};
但是,如果该覆盖包含需要在调用原始函数之前首先触发的异步回调,该怎么办,例如:
var render = res.render;
res.render = function() {
var self = this;
var args = arguments;
var middlewares = getSomeMiddleware();
return callNextMiddleware(middlewares, function() {
return render.apply(self, args);
});
};
function callNextMiddleware(middlewares, callback) {
var middlewareFunc = middlewares.shift();
if (middlewareFunc) {
return middlewareFunc.call(function() {
return callNextMiddleware(middlewares, callback);
});
}
else {
return callback();
}
}
请注意,我在需要时使用"return"语句。不过我有一个问题,"中间件"变量是一个函数数组,每个中间件函数如下所示:
function myMiddleware(next) {
performLongRunningAsyncDataAccess(function() {
next();
});
}
因为它不使用"return next((",所以原始 res.render 方法的返回值永远不会传回。如果我让所有中间件函数都使用"return next((",我可以让它工作,但它们来自外部来源,所以我无法控制它们,我只能保证它们会调用"next(("。
一点背景,这是一个 Node.js 应用程序。中间件基本上是连接中间件,我正在尝试覆盖 Express.js res.render 方法。
通常,将异步函数与return
语句混合使用是一个坏主意。你想要返回的所有内容,都可以作为参数传递给你的回调函数。所以我仍然希望我正确理解你的代码,但我假设你调用render
函数,然后获取一个middleware
函数数组。然后,您希望执行该数组中的所有函数,使用 next 作为对前一个函数的回调。执行完所有函数后,应再次调用render
函数,从而创建无限循环。假设所有这些,让我们来看看你的一些return
陈述:
return middlewareFunc.call(function() {
return callNextMiddleware(middlewares, callback);
});
此块中的第一个return
是无用的,因为middlewareFunc
是异步的,因此很可能会返回undefined
。第二个 return
语句也是无用的,因为它从函数返回,用作回调。但是由于您的回调只是使用 next();
调用的,因此永远不会使用返回值。
else {
return callback();
}
在此块中callback
是render
函数。那么让我们来看看这个函数:
res.render = function() {
var self = this;
var args = arguments;
var middlewares = getSomeMiddleware();
return callNextMiddleware(middlewares, function() {
return render.apply(self, args);
});
};
因此,所有最后三个return
语句基本上都存在,因为您希望从render
函数返回一些内容。但为了保持一致性,您还应该考虑对该函数使用回调:
res.render = function(callback) {
var self = this;
var args = arguments;
var middlewares = getSomeMiddleware();
callNextMiddleware(middlewares, function() {
//this will be called after all the middleware function have been executed
callback();
render.apply(self, args);
});
};
所以基本上你摆脱了所有的return
语句,并使用了纯粹的异步设计模式。
callNextMiddleware
应该返回其递归调用的返回值,而不是middlewareFunc
的返回值。
if (middlewareFunc) {
var result;
middlewareFunc.call(this, function() {
result = callNextMiddleware(middlewares, callback);
});
return result;
}
小提琴:http://jsfiddle.net/mWGXs
- 使用 jQuery 的 .on 函数如何获取事件的原始元素
- 我如何制作一个JS函数,它可以从相似的原始颜色双向更改为某个颜色
- jQuery's clone()函数扰乱了原始元素'的属性
- 为什么Coderbyte.com's的Javascript模板喜欢返回函数的原始参数
- 当将函数传递给方法时,为什么使用匿名函数容器而不仅仅是原始函数有效
- 如何将函数的参数重新分配回原始参数名称
- 函数中的拾取参数和使用原始参数的回调
- 两个函数使用相同的变量,都不会覆盖其原始变量
- jQuery 在缓存中预加载图像并在其他函数继续之前获取原始图像大小
- 如何在 JavaScript 中覆盖全局函数,但保留对原始函数的引用
- 在 JavaScript 函数之后保留原始数组
- 覆盖函数(例如“alert”)并调用原始函数
- 用于复制可能影响原始数组的数组的函数
- 如何在 for 循环中维护迭代变量的原始值,该循环设置事件调用,其中迭代值是函数的一部分
- 将其绑定到高阶函数中的原始对象
- 如何在不影响原始函数的情况下扩展javascript中的静态函数(使用新名称)
- JavaScript __proto__将影响对象中的原始函数
- 用于编辑原始对象的JavaScript函数
- 有可能用我的新上下文而不是原始的应用程序上下文来伪造WebView的构造函数吗
- 保持原始数组不变,更改函数中的本地副本