我正在使用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();
}
答案 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()
的逻辑将变得更易于理解和遵循。