使用typescript时nodejs中间件的这个范围

时间:2013-06-23 16:56:34

标签: node.js typescript

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

我正在使用打字稿:

/// <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) {

在构造函数中我看到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] }

1 个答案:

答案 0 :(得分:1)

使用箭头功能可保留this的含义。

您在这里使用箭头功能:

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

如果您不想保留this的范围,请改用标准函数:

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

当您执行此操作时,您会看到已编译的JavaScript中的_this变量将消失。

如果你想要两种意思,你可以手动存储上下文......

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