javascript - 在for循环中将文件异步写入服务器
问题描述
我正在尝试将我的原始代码转换为“异步”代码。
原始代码向数据库发送查询并检索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));
});
}
解释:
这个想法是你想让你的代码看起来像所有东西都被逐行阻塞时的样子。
和你可以做到这一点async
。await
当您将函数标记为async
允许您在其中运行await
时,它也包括for
循环。恰好节点 v10+fs
已promises
在其中定义以允许使用async
.
注意这个query
函数是如何产生的。这是将回调方法转变为promise
一种方法的典型方法。
推荐阅读
- hive - Hive 表(orc 类型)指向的 ORC 文件是否应该包含 hive 表中的所有属性?
- python-3.x - 在 Pandas 数据框中使用过滤器过滤行
- c# - c# StackFrame.GetILOffset()
- angular - 我应该总是使用 ChangeDetectionStrategy.OnPush
- jquery - 输入/数据列表自动完成不显示
- python - 在 PySpark 中将 2D 矩阵 - 数据框转换为平面表
- delphi - 如何在运行时显示 TDBGrid 列编辑器?
- c - 如何使用 getopt() 将带有参数的 args 分组
- javascript - 可以使用数学运算符 *、/、+、-、^ 将非零数转换为 1 吗?
- assembly - 如何将二进制值加载到寄存器中?