nodejs中间件在使用打字机时的这个范围

我正在尝试为我的nodejs服务器应用程序创build一个上传中间件。

我正在使用打字稿:

/// <reference path="./Scripts/typings/express/express.d.ts" /> /// <reference path="./Scripts/typings/async/async.d.ts" /> import file = module('modules/fileupload_file'); import async = module('async'); export class FileUpload { private uploadDelegate: any; constructor(options) { this.uploadDelegate = options.adapter || new file.filesystem(options); console.log(this.uploadDelegate); } middleware(req: ExpressServerRequest, res: ExpressServerResponse, next) { if (typeof req.files === 'undefined' || Object.keys(req.files).length === 0) { return next() } async.each( Object.keys(req.files), (field, cb) => { var files = req.files[field], filesArray = []; if (!Array.isArray(files)) files = [files]; async.each(files, (file, cb1) => { filesArray = []; if (typeof file.path === 'undefined' || file.size === 0) { return cb1(null); } console.log(this); this.uploadDelegate.put(file, function (error, storedFile) { filesArray.push(storedFile); cb1(null); }); }, (err: string) => { console.log(err); console.log(field); console.log(filesArray); req.body[field] = filesArray; cb(null); }); }, next); } } 

这变成:

 var file = require("./modules/fileupload_file"); var async = require('async'); var FileUpload = (function () { function FileUpload(options) { this.uploadDelegate = options.adapter || new file.filesystem(options); console.log(this.uploadDelegate); } FileUpload.prototype.middleware = function (req, res, next) { var _this = this; if (typeof req.files === 'undefined' || Object.keys(req.files).length === 0) { return next(); } async.each(Object.keys(req.files), function (field, cb) { var files = req.files[field], filesArray = []; if (!Array.isArray(files)) files = [files]; async.each(files, function (file, cb1) { filesArray = []; if (typeof file.path === 'undefined' || file.size === 0) { return cb1(null); } console.log(_this); _this.uploadDelegate.put(file, function (error, storedFile) { filesArray.push(storedFile); cb1(null); }); }, function (err) { console.log(err); console.log(field); console.log(filesArray); req.body[field] = filesArray; cb(null); }); }, next); }; return FileUpload; })(); exports.FileUpload = FileUpload; 

像这样使用它:

 app.post('/job/:name', myupload_middleware, function (req, res) { 

我现在的问题是我得到:

 TypeError: Cannot call method 'put' of undefined 

在行: _this.uploadDelegate.put(file, function (error, storedFile) {

在constructer我看到this.uploadDelegate已经设置。 console.log(_this)告诉我,这个范围是不是我所期望的?

 { ArrayBuffer: [Function: ArrayBuffer], Int8Array: { [Function: Int8Array] BYTES_PER_ELEMENT: 1 }, Uint8Array: { [Function: Uint8Array] BYTES_PER_ELEMENT: 1 }, Uint8ClampedArray: { [Function: Uint8ClampedArray] BYTES_PER_ELEMENT: 1 }, Int16Array: { [Function: Int16Array] BYTES_PER_ELEMENT: 2 }, Uint16Array: { [Function: Uint16Array] BYTES_PER_ELEMENT: 2 }, Int32Array: { [Function: Int32Array] BYTES_PER_ELEMENT: 4 }, Uint32Array: { [Function: Uint32Array] BYTES_PER_ELEMENT: 4 }, Float32Array: { [Function: Float32Array] BYTES_PER_ELEMENT: 4 }, Float64Array: { [Function: Float64Array] BYTES_PER_ELEMENT: 8 }, DataView: [Function: DataView], DTRACE_NET_SERVER_CONNECTION: [Function], DTRACE_NET_STREAM_END: [Function], DTRACE_NET_SOCKET_READ: [Function], DTRACE_NET_SOCKET_WRITE: [Function], DTRACE_HTTP_SERVER_REQUEST: [Function], DTRACE_HTTP_SERVER_RESPONSE: [Function], DTRACE_HTTP_CLIENT_REQUEST: [Function], DTRACE_HTTP_CLIENT_RESPONSE: [Function], COUNTER_NET_SERVER_CONNECTION: [Function], COUNTER_NET_SERVER_CONNECTION_CLOSE: [Function], COUNTER_HTTP_SERVER_REQUEST: [Function], COUNTER_HTTP_SERVER_RESPONSE: [Function], COUNTER_HTTP_CLIENT_REQUEST: [Function], COUNTER_HTTP_CLIENT_RESPONSE: [Function], global: [Circular], process: { title: 'Administrator: Node.js command prompt - node app.js', version: 'v0.10.12', moduleLoadList: [ 'Binding evals', 'Binding natives', 'NativeModule events', 'NativeModule buffer', 'Binding buffer', 'NativeModule assert', 'NativeModule util', 'NativeModule path', 'NativeModule module', 'NativeModule fs', 'Binding fs', 'Binding constants', 'NativeModule stream', 'NativeModule _stream_readable', 'NativeModule _stream_writable', 'NativeModule _stream_duplex', 'NativeModule _stream_transform', 'NativeModule _stream_passthrough', 'NativeModule http', 'NativeModule net', 'NativeModule timers', 'Binding timer_wrap', 'NativeModule _linklist', 'Binding cares_wrap', 'NativeModule url', 'NativeModule punycode', 'NativeModule querystring', 'NativeModule freelist', 'Binding http_parser', 'NativeModule crypto', 'Binding crypto', 'NativeModule string_decoder', 'NativeModule tty', 'Binding tty_wrap', 'NativeModule zlib', 'Binding zlib', 'NativeModule os', 'Binding os', 'NativeModule console', 'Binding signal_wrap', 'Binding tcp_wrap', 'NativeModule cluster', 'NativeModule child_process', 'NativeModule dgram', 'Binding udp_wrap', 'Binding process_wrap' ], versions: { http_parser: '1.0', node: '0.10.12', v8: '3.14.5.9', ares: '1.9.0-DEV', uv: '0.10.11', zlib: '1.2.3', modules: '11', openssl: '1.0.1e' }, arch: 'x64', platform: 'win32', argv: [ 'node', 'D:\\GitHub\\unix-node-js-samples\\AzureHelloWorld\\app.js' ], execArgv: [], env: { ALLUSERSPROFILE: 'C:\\ProgramData', AMDAPPSDKROOT: 'C:\\Program Files (x86)\\AMD APP\\', APPDATA: 'C:\\Users\\Administrator\\AppData\\Roaming', CommonProgramFiles: 'C:\\Program Files\\Common Files', 'CommonProgramFiles(x86)': 'C:\\Program Files (x86)\\Common Files', CommonProgramW6432: 'C:\\Program Files\\Common Files', COMPUTERNAME: 'SERVER-PC', ComSpec: 'C:\\Windows\\system32\\cmd.exe', FP_NO_HOST_CHECK: 'NO', HOMEDRIVE: 'C:', HOMEPATH: '\\Users\\Administrator', LOCALAPPDATA: 'C:\\Users\\Administrator\\AppData\\Local', LOGONSERVER: '\\\\SERVER-PC', NUMBER_OF_PROCESSORS: '8', OS: 'Windows_NT', Path: 'C:\\Users\\Administrator\\AppData\\Roaming\\npm;C:\\Program Files \\nodejs\\;C:\\Program Files (x86)\\AMD APP\\bin\\x86_64;C:\\Program Files (x86) \\AMD APP\\bin\\x86;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbe m;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\ATI Technologies\\ATI.ACE\\Core-Static;C:\\Program Files (x86)\\Microsoft ASP.NET\\A SP.NET Web Pages\\v1.0\\;C:\\Program Files\\Microsoft SQL Server\\110\\Tools\\Bi nn\\;C:\\Program Files\\MATLAB\\R2012b\\runtime\\win64;C:\\Program Files\\MATLAB \\R2012b\\bin;C:\\Program Files\\Microsoft\\Web Platform Installer\\;C:\\Program Files (x86)\\Microsoft SDKs\\TypeScript\\;C:\\Program Files\\nodejs\\;C:\\Users \\Administrator\\AppData\\Roaming\\npm', PATHEXT: '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC', PROCESSOR_ARCHITECTURE: 'AMD64', PROCESSOR_IDENTIFIER: 'Intel64 Family 6 Model 26 Stepping 5, GenuineInte l', PROCESSOR_LEVEL: '6', PROCESSOR_REVISION: '1a05', ProgramData: 'C:\\ProgramData', ProgramFiles: 'C:\\Program Files', 'ProgramFiles(x86)': 'C:\\Program Files (x86)', ProgramW6432: 'C:\\Program Files', PROMPT: '$P$G', PSModulePath: 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\ ;C:\\Program Files (x86)\\Microsoft SDKs\\Windows Azure\\PowerShell\\', PUBLIC: 'C:\\Users\\Public', SESSIONNAME: 'Console', SSH_AGENT_PID: '5316', SSH_AUTH_SOCK: '/tmp/ssh-aTYruZ5256/agent.5256', SystemDrive: 'C:', SystemRoot: 'C:\\Windows', TEMP: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\1', TMP: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\1', USERDOMAIN: 'SERVER-PC', USERDOMAIN_ROAMINGPROFILE: 'SERVER-PC', USERNAME: 'Administrator', USERPROFILE: 'C:\\Users\\Administrator', VS110COMNTOOLS: 'C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\ Common7\\Tools\\', windir: 'C:\\Windows' }, pid: 7776, features: { debug: false, uv: true, ipv6: true, tls_npn: true, tls_sni: true, tls: true }, _needImmediateCallback: false, execPath: 'C:\\Program Files\\nodejs\\node.exe', debugPort: 5858, _getActiveRequests: [Function], _getActiveHandles: [Function], _needTickCallback: [Function], reallyExit: [Function], abort: [Function], chdir: [Function], cwd: [Function], umask: [Function], _kill: [Function], _debugProcess: [Function], _debugPause: [Function], _debugEnd: [Function], hrtime: [Function], dlopen: [Function], uptime: [Function], memoryUsage: [Function], binding: [Function], _usingDomains: [Function], _tickInfoBox: { '0': 0, '1': 0, '2': 0 }, _events: { SIGWINCH: [Function] }, domain: null, _maxListeners: 10, EventEmitter: { [Function: EventEmitter] listenerCount: [Function] }, _fatalException: [Function], _exiting: false, assert: [Function], config: { target_defaults: [Object], variables: [Object] }, nextTick: [Function: nextTick], _nextDomainTick: [Function: _nextDomainTick], _tickCallback: [Function: _tickCallback], _tickDomainCallback: [Function: _tickDomainCallback], _tickFromSpinner: [Function: _tickFromSpinner], maxTickDepth: 1000, stdout: [Getter], stderr: [Getter], stdin: [Getter], openStdin: [Function], exit: [Function], kill: [Function], addListener: [Function], on: [Function], removeListener: [Function], mainModule: { id: '.', exports: {}, parent: null, filename: 'D:\\GitHub\\unix-node-js-samples\\AzureHelloWorld\\app.js', loaded: true, children: [Object], paths: [Object] }, _immediateCallback: [Function: processImmediate], _errno: 'EALREADY' }, GLOBAL: [Circular], root: [Circular], Buffer: { [Function: Buffer] isEncoding: [Function], poolSize: 8192, isBuffer: [Function: isBuffer], byteLength: [Function], concat: [Function], _charsWritten: 38 }, setTimeout: [Function], setInterval: [Function], clearTimeout: [Function], clearInterval: [Function], setImmediate: [Function], clearImmediate: [Function], console: [Getter] } 

使用箭头函数保留了这个意思。

您在这里使用箭头function:

 async.each( Object.keys(req.files), (field, cb) => { 

如果您不想保留这个范围,请使用标准函数:

 async.each( Object.keys(req.files), function (field, cb) { 

当你这样做的时候,你会发现编译过的JavaScript中的_thisvariables会消失。

如果你想要两个含义,你可以手动存储上下文…

 var _self = this; async.each( Object.keys(req.files), function (field, cb) { // self is the "outer this" // this is the "inner this"