首页 > 解决方案 > 在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.

标签: javascriptnode.jsasynchronous

解决方案


蒸馏的

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+fspromises在其中定义以允许使用async.

注意这个query函数是如何产生的。这是将回调方法转变为promise一种方法的典型方法。


推荐阅读