Ale*_*lls 7 javascript dependency-injection node.js typescript ecmascript-next
我想通过名字注入lodash,如下所示:
let val = function(lodash){
// lodash will be injected, simply by using require('lodash');
};
Run Code Online (Sandbox Code Playgroud)
但是说我要重命名导入,我想做这样的事情:
let val = function({lodash:_}){
};
Run Code Online (Sandbox Code Playgroud)
要么
let val = function(lodash as _){
};
Run Code Online (Sandbox Code Playgroud)
有没有办法用ES6/ES7/ES8或TypeScript做到这一点?
请注意,这个DI框架比仅需要('x')做更多的工作......它将首先尝试注入其他值,如果没有其他值,那么它将尝试要求该值.
另请注意,这里的要求是当您调用val.toString()时,"lodash"将被视为参数名称.但是在函数体内的运行时会看到_而不是lodash.这是因为为了注入lodash,我们调用fn.toString()来获取参数名称.
这里是npm包di-proxy
的链接(灵感来自这个答案),具有100%的代码覆盖率,并支持memoization以提高性能,与Node.js兼容>=6.0.0
.
这里是一个真棒解决方案,我想通了,而摆弄周围物体拆解和Proxy
:
/* MIT License */
/* Copyright 2017 Patrick Roberts */
// dependency injection utility
function inject(callbackfn) {
const handler = {
get(target, name) {
/* this is just a demo, swap these two lines for actual injection */
// return require(name);
return { name };
}
};
const proxy = new Proxy({}, handler);
return (...args) => callbackfn.call(this, proxy, ...args);
}
// usage
// wrap function declaration with inject()
const val = inject(function ({ lodash: _, 'socket.io': sio, jquery: $, express, fs }, other, args) {
// already have access to lodash, no need to even require() here
console.log(_);
console.log(sio);
console.log($);
console.log(express);
console.log(fs);
console.log(other, args);
});
// execute wrapped function with automatic injection
val('other', 'args');
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
max-height: 100% !important;
}
Run Code Online (Sandbox Code Playgroud)
通过对象解构将参数传递给函数会调用对象文字上每个属性的getter方法,以便在执行函数时确定值.
如果要解析的对象初始化为a Proxy
,则可以使用对尝试解析的属性名称的引用来拦截每个getter调用,并返回您选择使用的值来解析它.在这种情况下,分辨率应该是require(name)
,只需在函数对象参数中将其指定为属性名称即可注入模块.
下面是一个演示的链接,您可以在其中实际看到它在Node.js中工作.
这是该演示中的代码仅供参考,因为它在更大程度上演示了对象解构:
/* MIT License */
/* Copyright 2017 Patrick Roberts */
// dependency injection utility
function inject(callbackfn) {
const handler = {
get(target, name) {
return require(name);
}
};
const proxy = new Proxy({}, handler);
return (...args) => callbackfn.call(this, proxy, ...args);
}
// usage
// wrap function declaration with inject()
const val = inject(function ({
fs: { readFile: fsRead, writeFile: fsWrite },
child_process: { fork: cpF, spawn: cpS, exec: cpE },
events: { EventEmitter }
}, other, args) {
// already have access to modules, no need to require() here
console.log('fs:', { fsRead, fsWrite });
console.log('child_process:', { fork: cpF, spawn: cpS, exec: cpE });
console.log('EventEmitter:', EventEmitter);
console.log(other, args);
});
// execute wrapped function with automatic injection
val('other', 'args');
Run Code Online (Sandbox Code Playgroud)
如上所述,我已经发布了一个完整的npm包来实现这个概念.如果您喜欢这种语法,我建议您查看它,并希望比这个非常基本的示例更具性能和测试性.