We have two typescript class. On of them define a method as an object argument then transmitted in another class.
class MyService {
public options: { [key: string]: any };
constructor() { }
public upload(file: File): void {
const parallelHasher = new ParallelHasher('/public/md5_worker.js');
this.options = {
concurrency: 1,
autoUpload: true,
hashMethod: parallelHasher.hash // HERE
};
const uploadService = new UploadService(this.options);
this.uploadsProgress = uploadService.start(file)
}
}
class UploadService {
constructor(public options: any) { }
public async start(file: File): Promise<void> {
const hash = await this.options.hashMethod(file);
this.proceed(file, hash);
}
public proceed(file: File, hash: string): void {
// do something
}
}
We encounter an error when UploadService.start()
is called due to the hash method of the third party:
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'push' of undefined
TypeError: Cannot read property 'push' of undefined
at parallel_hasher.js:25
Here is the relevant part in third party code:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var ParallelHasher = (function () {
function ParallelHasher(workerUri) {
this._queue = [];
this._ready = true;
var self = this;
if (Worker) {
self._hashWorker = new Worker(workerUri);
self._hashWorker.onmessage = self._recievedMessage.bind(self);
self._hashWorker.onerror = function (err) {
self._ready = false;
console.error('Hash worker failure', err);
};
}
else {
self._ready = false;
console.error('Web Workers are not supported in this browser');
}
}
ParallelHasher.prototype.hash = function (blob) {
var self = this;
var promise;
promise = new Promise(function (resolve, reject) {
self._queue.push({
blob: blob,
resolve: resolve,
reject: reject,
});
self._processNext();
});
return promise;
};
return ParallelHasher;
}());
exports.ParallelHasher = ParallelHasher;
As you can see _queue
is defined in the constructor and should be there when the hash()
method tries to use it to push new element to queue.
By placing a debugger on the line with var self = this;
in the third party's hash
method, the value of this
is equivalent to this.options
in MyService
class, instead of being ParallelHasher
:
concurrency: 1,
autoUpload: true,
hashMethod: parallelHasher.hash
And indeed, there is no _queue
in options, hence the error.
Somehow, the context of the third party's method call is set, not in the ParallelHasher
instance but in the options
object.
I don't really understand why, and how to prevent this from occuring.