Skip to content

Commit c743527

Browse files
authoredApr 14, 2024··
Break the huge promise chain (#257)
* Break the huge promise chain, use a loop By using a loop over all records instead of building a huge promise chain, we avoid the issue documented in #254 where the promise chain ends up taking up all the memory of an application. In short, this commit allows the garbage collector to collect the small promises as they resolve, rather than building one huge chain that keeps references to the future "then"s. The downside of this approach currently is that it relies on async/await syntax in order to allow awaits inside loops, which is what can fix the issue here. Im sure we can find a solution without this if it is significant, and we put our minds to it! * Async-free solution with no eternal promise chain In this approach, I have removed the dependency on async/await syntax, but also avoided eternal promise chains by using a top-level promise that allows sub-promises to compute to fulfillment before moving on.
1 parent 7b3c0b4 commit c743527

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed
 

‎lib/parse.js

+10-7
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ util.inherits(Parse, PullStream);
3434

3535
Parse.prototype._readRecord = function () {
3636
var self = this;
37+
3738
return self.pull(4).then(function(data) {
3839
if (data.length === 0)
3940
return;
@@ -63,7 +64,11 @@ Parse.prototype._readRecord = function () {
6364
}
6465
else
6566
self.emit('error', new Error('invalid signature: 0x' + signature.toString(16)));
66-
});
67+
}).then((function(loop) {
68+
if(loop) {
69+
return self._readRecord();
70+
}
71+
}));
6772
};
6873

6974
Parse.prototype._readCrxHeader = function() {
@@ -79,7 +84,7 @@ Parse.prototype._readCrxHeader = function() {
7984
self.crxHeader.publicKey = data.slice(0,self.crxHeader.pubKeyLength);
8085
self.crxHeader.signature = data.slice(self.crxHeader.pubKeyLength);
8186
self.emit('crx-header',self.crxHeader);
82-
return self._readRecord();
87+
return true;
8388
});
8489
};
8590

@@ -187,9 +192,7 @@ Parse.prototype._readFile = function () {
187192
.on('error',function(err) { self.emit('error',err);})
188193
.pipe(entry)
189194
.on('finish', function() {
190-
return fileSizeKnown ?
191-
self._readRecord().then(resolve).catch(reject) :
192-
self._processDataDescriptor(entry).then(resolve).catch(reject);
195+
return fileSizeKnown ? resolve(fileSizeKnown) : self._processDataDescriptor(entry).then(resolve).catch(reject);
193196
});
194197
});
195198
});
@@ -208,7 +211,7 @@ Parse.prototype._processDataDescriptor = function (entry) {
208211
]);
209212

210213
entry.size = vars.uncompressedSize;
211-
return self._readRecord();
214+
return true;
212215
});
213216
};
214217

@@ -242,7 +245,7 @@ Parse.prototype._readCentralDirectoryFileHeader = function () {
242245
return self.pull(vars.fileCommentLength);
243246
})
244247
.then(function(fileComment) {
245-
return self._readRecord();
248+
return true;
246249
});
247250
});
248251
};

0 commit comments

Comments
 (0)
Please sign in to comment.