@@ -579,15 +579,17 @@ RedisClient.prototype.return_reply = function (reply) {
579579
580580 if ( command_obj && ! command_obj . sub_command ) {
581581 if ( typeof command_obj . callback === "function" ) {
582- if ( this . options . detect_buffers && command_obj . buffer_args === false && 'exec' !== command_obj . command ) {
583- // If detect_buffers option was specified, then the reply from the parser will be Buffers.
584- // If this command did not use Buffer arguments, then convert the reply to Strings here.
585- reply = reply_to_strings ( reply ) ;
586- }
582+ if ( 'exec' !== command_obj . command ) {
583+ if ( this . options . detect_buffers && command_obj . buffer_args === false ) {
584+ // If detect_buffers option was specified, then the reply from the parser will be Buffers.
585+ // If this command did not use Buffer arguments, then convert the reply to Strings here.
586+ reply = reply_to_strings ( reply ) ;
587+ }
587588
588- // TODO - confusing and error-prone that hgetall is special cased in two places
589- if ( reply && 'hgetall' === command_obj . command ) {
590- reply = reply_to_object ( reply ) ;
589+ // TODO - confusing and error-prone that hgetall is special cased in two places
590+ if ( reply && 'hgetall' === command_obj . command ) {
591+ reply = reply_to_object ( reply ) ;
592+ }
591593 }
592594
593595 command_obj . callback ( null , reply ) ;
@@ -993,92 +995,88 @@ Multi.prototype.hmset = Multi.prototype.HMSET = function (key, args, callback) {
993995 return this ;
994996} ;
995997
998+ Multi . prototype . send_command = function ( command , args , cb ) {
999+ var self = this ;
1000+ this . _client . send_command ( command , args , function ( err , reply ) {
1001+ if ( err ) {
1002+ if ( cb ) {
1003+ cb ( err ) ;
1004+ } else {
1005+ self . errors . push ( err ) ;
1006+ }
1007+ }
1008+ } ) ;
1009+ } ;
1010+
9961011Multi . prototype . exec = Multi . prototype . EXEC = function ( callback ) {
9971012 var self = this ;
998- var errors = [ ] ;
999- var wants_buffers = [ ] ;
1013+ this . errors = [ ] ;
1014+ this . callback = callback ;
1015+ this . wants_buffers = new Array ( this . queue . length ) ;
10001016 // drain queue, callback will catch "QUEUED" or error
1001- // TODO - get rid of all of these anonymous functions which are elegant but slow
1002- this . queue . forEach ( function ( args , index ) {
1003- var command = args [ 0 ] , obj , i , il , buffer_args ;
1017+ for ( var index = 0 ; index < this . queue . length ; index ++ ) {
1018+ var args = this . queue [ index ] . slice ( ) ;
1019+ var command = args . shift ( ) ;
1020+ var cb ;
10041021 if ( typeof args [ args . length - 1 ] === "function" ) {
1005- args = args . slice ( 1 , - 1 ) ;
1006- } else {
1007- args = args . slice ( 1 ) ;
1022+ cb = args . pop ( ) ;
10081023 }
10091024 // Keep track of who wants buffer responses:
1010- buffer_args = false ;
1011- for ( i = 0 , il = args . length ; i < il ; i += 1 ) {
1025+ this . wants_buffers [ index ] = false ;
1026+ for ( var i = 0 ; i < args . length ; i += 1 ) {
10121027 if ( Buffer . isBuffer ( args [ i ] ) ) {
1013- buffer_args = true ;
1028+ this . wants_buffers [ index ] = true ;
1029+ break ;
10141030 }
10151031 }
1016- wants_buffers . push ( buffer_args ) ;
1017- if ( args . length === 1 && Array . isArray ( args [ 0 ] ) ) {
1018- args = args [ 0 ] ;
1019- }
1020- if ( command === 'hmset' && typeof args [ 1 ] === 'object' ) {
1021- obj = args . pop ( ) ;
1022- Object . keys ( obj ) . forEach ( function ( key ) {
1023- args . push ( key ) ;
1024- args . push ( obj [ key ] ) ;
1025- } ) ;
1026- }
1027- this . _client . send_command ( command , args , function ( err , reply ) {
1028- if ( err ) {
1029- var cur = self . queue [ index ] ;
1030- if ( typeof cur [ cur . length - 1 ] === "function" ) {
1031- cur [ cur . length - 1 ] ( err ) ;
1032- } else {
1033- errors . push ( err ) ;
1034- }
1035- }
1036- } ) ;
1037- } , this ) ;
1032+ this . send_command ( command , args , cb ) ;
1033+ }
10381034
1039- // TODO - make this callback part of Multi.prototype instead of creating it each time
1040- return this . _client . send_command ( "exec" , [ ] , function ( err , replies ) {
1041- if ( err && ! err . code ) {
1042- if ( callback ) {
1043- errors . push ( err ) ;
1044- callback ( errors ) ;
1045- return ;
1035+ this . _client . send_command ( 'exec' , [ ] , function ( err , replies ) {
1036+ self . execute_callback ( err , replies ) ;
1037+ } ) ;
1038+ } ;
1039+
1040+ Multi . prototype . execute_callback = function ( err , replies ) {
1041+ var i , reply , args ;
1042+
1043+ if ( err ) {
1044+ if ( err . code !== 'CONNECTION_BROKEN' ) {
1045+ if ( this . callback ) {
1046+ this . errors . push ( err ) ;
1047+ this . callback ( this . errors ) ;
10461048 } else {
1047- self . _client . emit ( 'error' , err ) ;
1049+ // Exclude CONNECTION_BROKEN so that error won't be emitted twice
1050+ this . _client . emit ( 'error' , err ) ;
10481051 }
10491052 }
1053+ return ;
1054+ }
10501055
1051- var i , il , reply , to_buffer , args ;
1052-
1053- if ( replies ) {
1054- for ( i = 1 , il = self . queue . length ; i < il ; i += 1 ) {
1055- reply = replies [ i - 1 ] ;
1056- args = self . queue [ i ] ;
1057- to_buffer = wants_buffers [ i ] ;
1056+ if ( replies ) {
1057+ for ( i = 1 ; i < this . queue . length ; i += 1 ) {
1058+ reply = replies [ i - 1 ] ;
1059+ args = this . queue [ i ] ;
10581060
1059- // If we asked for strings, even in detect_buffers mode, then return strings:
1060- if ( self . _client . options . detect_buffers && to_buffer === false ) {
1061- replies [ i - 1 ] = reply = reply_to_strings ( reply ) ;
1062- }
1061+ // If we asked for strings, even in detect_buffers mode, then return strings:
1062+ if ( this . _client . options . detect_buffers && this . wants_buffers [ i ] === false ) {
1063+ replies [ i - 1 ] = reply = reply_to_strings ( reply ) ;
1064+ }
10631065
1064- // TODO - confusing and error-prone that hgetall is special cased in two places
1065- if ( reply && args [ 0 ] === "hgetall" ) {
1066- replies [ i - 1 ] = reply = reply_to_object ( reply ) ;
1067- }
1066+ // TODO - confusing and error-prone that hgetall is special cased in two places
1067+ if ( reply && args [ 0 ] === "hgetall" ) {
1068+ replies [ i - 1 ] = reply = reply_to_object ( reply ) ;
1069+ }
10681070
1069- if ( typeof args [ args . length - 1 ] === "function" ) {
1070- args [ args . length - 1 ] ( null , reply ) ;
1071- }
1071+ if ( typeof args [ args . length - 1 ] === "function" ) {
1072+ args [ args . length - 1 ] ( null , reply ) ;
10721073 }
10731074 }
1075+ }
10741076
1075- if ( callback ) {
1076- callback ( null , replies ) ;
1077- } else if ( err && err . code !== 'CONNECTION_BROKEN' ) {
1078- // Exclude CONNECTION_BROKEN so that error won't be emitted twice
1079- self . _client . emit ( 'error' , err ) ;
1080- }
1081- } ) ;
1077+ if ( this . callback ) {
1078+ this . callback ( null , replies ) ;
1079+ }
10821080} ;
10831081
10841082RedisClient . prototype . multi = RedisClient . prototype . MULTI = function ( args ) {
0 commit comments