向数据库添加新记录时的UnhandledPromiseRejectionWarning

时间:2019-05-31 09:38:55

标签: node.js mongoose

我正在尝试将新记录添加到我的MongoDB数据库中。记录以数组的形式出现,然后,对于每条记录,我将其作为新项添加到MongoDB中。 问题是每次我尝试添加一些记录(30-50条记录)时,都会显示以下消息:

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()

之后是这个:

UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

这是我用来添加记录的代码段:

// update the blacklist with a new entry
router.post("/updateBlacklist", async (req, res) => {
  req.body.product_id.forEach(async element => {
    const blacklistItem = new Blacklist({ product_id: element });
    try {
      const savedItem = await blacklistItem.save();
      res.json(savedItem);
    } catch (err) {
      console.log(err);
      res.json({ message: err });
    }
  });
});

当我尝试使用此功能下载一些照片时,也会出现相同的警告:

router.post("/product_ids", async (req, res) => {
  await downloadPhotos(req.body.items_id);
});

我在此路由内调用的函数:

const axios = require("axios");
const download = require("./utils/download");

const downloadPhotos = async itemsIDs => {
  try {
    console.log(itemsIDs.length);
    await itemsIDs.forEach(ID => {
      axios
        .get(
          `https://${process.env.SHOPIFY_API_KEY}:${
            process.env.SHOPIFY_PASSWORD
          }@blablabla.myshopify.com/admin/products/${ID}/images.json?fields=id, src`
        )
        .then((req, res) => {
          console.log(req.data.images[0].src);
          download(req.data.images[0].src, req.data.images[0].id, 3000);
        });
    });
  } catch (err) {
    console.log(err);
  }
};

download函数:

const Fs = require("fs");
const Path = require("path");
const Axios = require("axios");

async function downloadImage(url, filename, timeout) {
  const appDir = Path.dirname(require.main.filename);
  const path = Path.resolve(appDir, "images", `${filename}.jpg`);

  const writer = Fs.createWriteStream(path);

  const response = await Axios({
    url,
    method: "GET",
    responseType: "stream",
    timeout: timeout
  });

  response.data.pipe(writer);

  return new Promise((resolve, reject) => {
    writer.on("finish", resolve);
    writer.on("error", reject);
  });
}

module.exports = downloadImage;

在这种方法下我做错了什么?

1 个答案:

答案 0 :(得分:1)

This error:

UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

It's because of these lines:

res.json(savedItem);    
res.json({ message: err });

You're running these lines several times, because they are inside the loop, you can't respond a request more than once because the connection it's closed after the first call.

Try with this:

router.post("/updateBlacklist", async (req, res) => {
  const savedList = [];
  req.body.product_id.forEach(async element => {
    const blacklistItem = new Blacklist({ product_id: element });
    try {
      const savedItem = await blacklistItem.save();
      savedList.push(savedItem)
    } catch (err) {
      console.log(err);
      savedList.push({ message: err });
    }
  });
  res.json(savedItem);
});

UPDATE (suggestion):

router.post("/updateBlacklist", async (req, res) => {
  const items = req.body.product_id.map(element => 
     new Blacklist({ product_id: element })
  });
  const result = await Blacklist.insertMany(items); // not sure about the syntax
  res.json(result);
});