将文件异步写入循环中的服务器



我正在尝试将我的原始代码转换为"异步;密码

原始代码向数据库发送查询并检索results。结果还包含一个图像。我想异步地将图像写入我的nodejs服务器。目前,写入是同步的,这给RAM带来了很大的压力。

下面你可以看到原始代码和我创建异步代码的尝试,我哪里出错了?

这是原始代码:

db.query("SELECT imageID, imageBlob FROM sys.users_image;", function (err, result, fields) {
console.log("Downloading images from database...")
if (err) throw err;
//Make await
for (let i = 0; i < result.length; i++) {
let binaryBuffer= result[i].imageBlob;
let imageID= result[i].imageID;
let image = binaryBuffer.toString('binary');
fs.writeFile('public/images/shareImg/'+imageID, image, {encoding: 'base64'},  function (err) {
if (err) {
console.log(err)
} else {
console.log("file written " + i)
}
})
console.log(i)
}
});

我查阅了多个教程和示例,但我能弄清楚,这是我的尝试。

async function test(result) {
//Correctly logs result and  result.length
console.log(result[0])
console.log(result.length)
for (let i = 0; i < result.length; i++) {
//UnhandledPromiseRejectionWarning: ReferenceError: result is not defined
//Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
console.log(result)

console.log('Before await for ', i);
let binaryBuffer= result[i].imageBlob;
let imageID= result[i].imageID;
let image = binaryBuffer.toString('binary');
fs.writeFile('public/images/shareImg/'+imageID, image, {encoding: 'base64'},  function (err) {
if (err) {
console.log(err)
} else {
console.log("file written " + i)
}
})
let result = await Promise.resolve(i);
console.log('After await. Value is ', result);
}
}
//db query
db.query("SELECT imageID, imageBlob FROM sys.users_image;", function (err, result, fields) {
console.log("Downloading images from database...")
if (err) throw err;

//import result from db
test(result).then(_ => console.log('After test() resolved'));
});

这是日志输出:

Downloading images from database...
RowDataPacket {
imageID: '1609328903457.png',
imageBlob:
<Buffer 69 56 42 4f 52 77 30 4b 47 67 6f 41 41 41 41 4e 53 55 68 45 55 67 41 41 42 7a 67 41 41 41 4f 49 43 41 49 41 41 41 41 6c 2f 62 41 69 41 41 41 41 43 58 ... > }
20
(node:24318) UnhandledPromiseRejectionWarning: ReferenceError: result is not defined
(node:24318) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
(node:24318) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

蒸馏

import { promises as fs } from 'fs';
async function test() {
const results = await query('SELECT imageID, imageBlob FROM sys.users_image;');
for (const result of results) {
const { imageBlob, imageID } = result;
const image = imageBlob.toString('binary');
await fs.writeFile(`public/images/shareImg/${imageID}`, image, {encoding: 'base64'});
}
}
async function query(q) {
return new Promise((resolve, reject) => {
db.query(q, (err, result, fields) => err ? reject(err) : resolve(result));
});
}

解释:

这个想法是,你想让你的代码看起来像是在所有东西都被逐行阻塞的情况下。

使用asyncawait,您可以做到这一点。当您将函数标记为async时,它允许您在其中运行await,其中也包括for循环。恰好节点v10+fs中定义了promises,以便使用async进行简单的行为。

请注意query函数是如何生成的。这是将回调方法转换为promise方法的典型方法。

哪里出了问题:for是同步的,它立即运行,不等待writeFile完成

您应该使用for await...of语句对异步可迭代性进行迭代。

例如:

//Must Node.js v10.23.0
const fs = require("fs");
async function test(result) {
try {
let promiseResult = [];
for await (const data of result) {
let binaryBuffer = data.imageBlob;
let imageID = data.imageID;
let image = binaryBuffer.toString("binary");
//Write the file
const writeFile = await fs.await.writeFile(
"public/images/shareImg/" + imageID,
image,
{ encoding: "base64" }
);
//Save the resultat in a table
promiseResult.push(writeFile);
}
return promiseResult;
} catch (error) {
console.log(error);
throw error;
}
}
//db query
db.query("SELECT imageID, imageBlob FROM sys.users_image;", function(
err,
result,
fields
) {
console.log("Downloading images from database...");
if (err) throw err;
//import result from db
test(result).then(_ => console.log("After test() resolved"));
});

最新更新