使用存储为对象属性的类方法时,类实例丢失

时间:2019-04-23 00:06:44

标签: javascript typescript

我们有两个打字稿课。在它们上定义一个方法作为对象参数,然后在另一个类中进行传输。

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
    }
}

由于第三方的哈希方法,在调用UploadService.start()时遇到错误:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'push' of undefined
TypeError: Cannot read property 'push' of undefined
    at parallel_hasher.js:25

以下是第三方代码中的相关部分:

"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;

如您所见,_queue是在构造函数中定义的,并且在hash()方法尝试使用它来将新元素推入队列时应该存在。

通过在第三方的var self = this;方法中将调试器与hash放置在一起,this的值等效于this.options类中的MyService ,而不是ParallelHasher

concurrency: 1,
autoUpload: true,
hashMethod: parallelHasher.hash

实际上,选项中没有_queue,因此会出现错误。

以某种方式,不是在ParallelHasher实例中而是在options对象中设置了第三方方法调用的上下文。

我不太了解为什么以及如何防止这种情况发生。

1 个答案:

答案 0 :(得分:2)

库的parallelHasher.hash方法未绑定到this,因此当您传递方法本身时,它将丢失其this指针。相反,您可以在选项中创建一个匿名函数,以使库方法保持其this上下文,而无需修改库本身。

        this.options = {
            concurrency: 1,
            autoUpload: true,
            hashMethod: (blob) => {
                return parallelHasher.hash(blob);
            }
        };

以下一些文档值得阅读,以更好地了解正在发生的事情:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind