function WorkerIndex(options = /** @type IndexOptions */{}, encoder) {

    if (!this || this.constructor !== WorkerIndex) {
        return new WorkerIndex(options);
    }

    let factory = "undefined" != typeof self ? self._factory : "undefined" != typeof window ? window._factory : null;
    if (factory) {
        factory = factory.toString();
    }

    const is_node_js = "undefined" == typeof window,
          _self = this;

    /**
     * @this {WorkerIndex}
     */
    function init(worker) {

        this.worker = worker;
        this.resolver = create_object();

        if (!this.worker) {
            return;
        }

        function onmessage(msg) {
            msg = msg.data || msg;
            const id = msg.id,
                  res = id && _self.resolver[id];

            if (res) {
                res(msg.msg);
                delete _self.resolver[id];
            }
        }

        is_node_js ? this.worker.on("message", onmessage) : this.worker.onmessage = onmessage;

        if (options.config) {

            return new Promise(function (resolve) {
                if (1e9 < pid) pid = 0;
                _self.resolver[++pid] = function () {
                    resolve(_self);
                };
                _self.worker.postMessage({
                    id: pid,
                    task: "init",
                    factory: factory,
                    options: options
                });
            });
        }

        this.priority = options.priority || 4;


        this.encoder = encoder || null;

        this.worker.postMessage({
            task: "init",
            factory: factory,
            options: options
        });

        return this;
    }

    const worker = create(factory, is_node_js, options.worker);
    return worker.then ? worker.then(function (worker) {
        return init.call(_self, worker);
    }) : init.call(this, worker);
}
@param {IndexOptions=} options
@param {Encoder=} encoder
@constructor