异步/等待中的文件写入问题

问题描述 投票:0回答:1

这里,我试图检索对象并将其推入数组。由于某种原因,当文件中应包含更多对象时,只有一条记录被推入文件中。您能帮我解决这个问题还是让我知道我要去哪里错了?这是我的代码:

exports.createjson = (req, res, next) => {
  try {
    var myPromise = () => {
      // ...
    };
    var callMyPromise = async () => {
      const responsearray = [];
      var result = await myPromise();
      return new Promise((resolve, reject) => {
        result.forEach(element => {
          NewsModel.findOne({ _id: element.newsId }).exec(
            async (err, result) => {
              if (err) {
                throw err;
              }
              reportsModel
                .findOne({
                  $and: [
                    { userId: req.query.userId },
                    { newsId: element.newsId }
                  ]
                })
                .exec((err, newsResult) => {
                  if (err) {
                    throw err;
                  }
                  // console.log(newsResult);

                  var response = {
                    newsId: element.newsId,
                    title: result.title,
                    collection: result.group,
                    belivibalityIndex: element.belivibalityIndex,
                    priorknowledge: element.priorknowledge,
                    readingTime: element.readingTime,
                    userId: element.userId,
                    comment: element.comment,
                    report: newsResult !== null ? newsResult.feedback : null
                  };
                  // #all object pushed and displayed in console
                  responsearray.push(response);
                  console.log(response);
                  console.log(responsearray.length);
                  // let data = JSON.stringify(responsearray);
                  // #here is the issue          // fs.writeFileSync("abc.json", data, null, null, flag = 'a');
                  return responsearray;
                });
            }
          );
        });
      });
    };
    callMyPromise().then(function(responsearray) {
      res.json(responsearray);
    });
  } catch (error) {
    next(error);
  }
};
node.js async-await file-writing
1个回答
1
投票

您没有正确使用Promises。例如,创建一个Promise对象,但是从不调用resolve / reject函数。在forEach循环中,您正在调用使用回调的函数,完成此工作后,您可以resolve将其包装的诺言。

此外,当您处于forEach循环中时,您正在调用res.json并写入文件(尽管已将其注释掉)。这意味着res.json将被多次调用,这是不允许的。您只能从http请求中获得一个响应。

我重组了代码,以使其将所有promise收集在一个Promises数组中,然后等待所有Promise都解决。只有完成所有工作后,我们才能编写文件并调用res.json完成http请求。

exports.createjson = async (req, res, next) => {
  const responsearray = [];
  var elements = await myPromise();
  var promises = []; // collect a bunch of promises to wait on
  elements.forEach(element => {
    // one promise per element that resolves when response is on the array
    var promise = new Promise(function(resolve, reject) {
      NewsModel.findOne({ _id: element.newsId }).exec((err, result) => {
        if (err) { return reject(err); }
        reportsModel
          .findOne({
            $and: [{ userId: req.query.userId }, { newsId: element.newsId }]
          })
          .exec((err, newsResult) => {
            if (err) { return reject(err); }

            var response = { /* response body */ };
            responsearray.push(response);
            console.log(response);
            console.log(responsearray.length);
            // complete the promise now that the response is on the array
            return resolve(); 
          });
      });
    });
    // collect each promise in an array so we can wait for them all 
    promises.push(promise);
  });
  // wait for all the work to complete
  await Promise.all(promises).catch(err => next(err));
  // write the responsearray to a file as json 
  let data = JSON.stringify(responsearray);
  fs.writeFileSync("abc.json", data);
  return res.json(responsearray);
};

我还删除了try/catch块,因为Promise允许您以更简洁的方式使用.catch。它简化了嵌套,使其更易于阅读。

这里的重点是一般结构:

// get your array to work with
var array = await someFunction()
var manyPromises = []
var manyResults = []
// for each thing in the array create a promise
array.forEach( thing => {
  manyPromises.push( new Promise((resolve,reject) => {
    doSomething(thing, (err, result) => {
      if (err) return reject(err);
      // store the results in the array and resolve the promise
      manyResults.push(result)
      return resolve();
    });
  });
});
// wait for all promises in manyPromises to complete
await Promise.all(manyPromises).catch(err => return next(err));
// now the many promises are done and manyResponses are ready
saveResponsesToFile(JSON.stringify(manyResponses))
return res.json(manyReponses)
© www.soinside.com 2019 - 2024. All rights reserved.