等待跳过以及如何解决?

时间:2019-02-12 22:14:23

标签: javascript promise async-await

我正在使用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

此工具提供了examples,但我无法弄清楚如何为代码提​​供承诺

编辑:已添加 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 :(得分:1)

这就是我的建议。您有streamExportOBJ()试图同步运行,但是它正在调用实际上是异步的writer方法,因此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()的逻辑将变得更易于理解和遵循。