Жду пропуска и как исправить? - PullRequest
0 голосов
/ 13 февраля 2019

Я использую https://github.com/jimmywarting/StreamSaver.js для потоковой передачи некоторых геометрических данных в файл, однако я не могу заставить их работать с моими ограниченными знаниями Promise

        const fileStream = streamSaver.createWriteStream('export.obj')
        const writer = fileStream.getWriter()
        const encoder = new TextEncoder

        object.streamExportGeometry(async data => {    //Callback from streamExportGeometry with data to write. Called many times
            console.log("writerQueued");
            await new Promise((resolve, reject) => {
                writer.write(encoder.encode(data)).then(() => { setTimeout(resolve) })
            });
            console.log("writerDone");
        }, onProgress);
        writer.close()

Я перепробовал много вариантов await, но этоникогда не ждет, пока Writer.write завершит.Вывод на консоль выглядит следующим образом

24x writerQueued 24x writerQueued exported finished 24x writerDone 24x writerDone writerDone

Имеется примеров , предоставляемых с этим инструментом, но я не могу понять, как бы я размещал обещания для моего кода

Редактировать: добавлен streamExportGeometry

 streamExportOBJ(writer, onProgressCallback) {
    var i, j, k, l, x, y, z;

    var vertices = this._vertices ? this._vertices.array : null;

    //Buffer object, to optimize amount of lines per write
    var writeBuffer = {
        _outputBuffer: "",
        _currBuffer: 0,
        _bufferLineLimit: 10000,
        _progress: 0,
        _expectedProgress: 1 + (vertices ? vertices.length / 3 : 0) + (uvs ? uvs.length / 2 : 0) + (normals ? normals.length / 3 : 0) + (indices ? indices.length / 3 : vertices.length / 3),
        writeLine: function (data) {
            this._outputBuffer += data;
            this._currBuffer++;
            if (this._currBuffer >= this._bufferLineLimit)
                this.flush();
        },
        flush: function () {
            if (this._outputBuffer) {
                writer(this._outputBuffer);
                this._outputBuffer = "";
                this._progress += this._currBuffer;
                this._currBuffer = 0;
                onProgressCallback(this._progress / this._expectedProgress * 100);
            }
        }
    }

    writeBuffer.writeLine('o export\n');

    //vertices
    if (vertices !== undefined && vertices && vertices.length >= 3) {
        for (i = 0; i < vertices.length; i += 3) {
            x = vertices[i];
            y = vertices[i + 1];
            z = vertices[i + 2];

            writeBuffer.writeLine('v ' + x + ' ' + y + ' ' + z + '\n');
        }
    }

    //Some more data..

   writeBuffer.flush();
 }

1 Ответ

0 голосов
/ 13 февраля 2019

Это то, что я бы предложил.У вас есть streamExportOBJ(), который пытается вести себя синхронно, но он вызывает метод записи, который на самом деле является асинхронным, поэтому у streamExportOBJ() не было возможности узнать, когда был выполнен какой-либо асинхронный вызов, который он вызывал.Итак, я сделал обратный вызов, который вы передаете streamExportOBJ(), имеет асинхронный интерфейс, а затем streamExportOBJ() может await его.

Я не совсем уверен, что вы хотите сделать с обработкой ошибок здесь.Если в writer.write() возникают какие-либо ошибки, то весь процесс прерывается, и ошибка просачивается обратно на ваш верхний уровень, где его получает блок catch(e) {}.Вы могли бы разрабатывать различные стратегии там.

async streamExportOBJ(writer, onProgressCallback) {
    var i, j, k, l, x, y, z;

    var vertices = this._vertices ? this._vertices.array : null;

    //Buffer object, to optimize amount of lines per write
    var writeBuffer = {
        _outputBuffer: "",
        _currBuffer: 0,
        _bufferLineLimit: 10000,
        _progress: 0,
        _expectedProgress: 1 + (vertices ? vertices.length / 3 : 0) + (uvs ? uvs.length / 2 : 0) + (normals ? normals.length / 3 : 0) + (indices ? indices.length / 3 : vertices.length / 3),

        writeLine: async function (data) {
            this._outputBuffer += data;
            this._currBuffer++;
            if (this._currBuffer >= this._bufferLineLimit)
                return this.flush();
        },

        flush: async function () {
            if (this._outputBuffer) {
                await writer(this._outputBuffer);
                this._outputBuffer = "";
                this._progress += this._currBuffer;
                this._currBuffer = 0;
                onProgressCallback(this._progress / this._expectedProgress * 100);
            }
        }
    }

    await writeBuffer.writeLine('o export\n');

    //vertices
    if (vertices !== undefined && vertices && vertices.length >= 3) {
        for (i = 0; i < vertices.length; i += 3) {
            x = vertices[i];
            y = vertices[i + 1];
            z = vertices[i + 2];

            await writeBuffer.writeLine('v ' + x + ' ' + y + ' ' + z + '\n');
        }
    }

    //Some more data..

   return writeBuffer.flush();
}

async function someFunction() {
    const fileStream = streamSaver.createWriteStream('export.obj');
    const writer = fileStream.getWriter();
    const encoder = new TextEncoder;

    try {
        await object.streamExportGeometry(async data => {
            console.log("writerQueued");
            await writer.write(encoder.encode(data));
            console.log("writerDone");
        }, onProgress);
    } catch(e) {
        // not sure what you want to do here when there 
        // was an error somewhere in object.streamExportGeometry()
    } finally {
        // always close
        writer.close()
    }
}

К вашему сведению, если бы это был мой код, я бы переместил все функции writeBuffer в свой собственный класс и вывел бы их из streamExportObj.Похоже, что это общая функция буферизации и может быть реализована / протестирована отдельно, и тогда логика streamExportOBJ() будет проще понять и следовать.

...