简体   繁体   English

Nodejs 似乎在等待包含 Promise 的函数解析之前返回响应

[英]Nodejs appears to return a response before waiting for functions containing Promises to resolve

I am trying to hit my API endpoint 'categories' to return a list of documents from my categories collection in firebase.我正在尝试点击我的 API 端点“类别”以从 firebase 中的类别集合返回文档列表。 Using the following code:使用以下代码:

function getCategories() {
  let arr = [];
  categories
    .get()
    .then(snapshot => {
      snapshot.forEach(doc => {
        console.log(doc.data().category);
        arr.push(doc.data().category);
        return arr;
      });
    })
    .catch(err => {
      console.log(err);
      return [1, 2, 3];
    });
}

router.route("/categories").get(async function(req, res, next) {
  let arr = await getCategories();
  res.json(arr);
});

While I don't get any errors I receive an empty response which when debugged shows that arr is undefined.虽然我没有收到任何错误,但我收到一个空响应,在调试时显示arr未定义。 The thing is when using the debugger the console logs inside the forEach get called and I see my categories in the console but for some reason, it doesn't wait for the Firebase Promise to resolve and the router just responds with an undefined arr variable.问题是当使用调试器时, forEach的控制台日志被调用,我在控制台中看到了我的类别,但由于某种原因,它不会等待 Firebase Promise 解析,路由器只是用未定义的arr变量进行响应。

Your .then callback should look more like this (there is no need for a separate arr variable):您的.then回调应该更像这样(不需要单独的arr变量):

function getCategories() {
  // notice we are returning the promise
  return categories
    .get()
    .then(snapshot => {
      // notice we are returning the new array using .map()
      return snapshot.map(doc => {
        console.log(doc.data().category);
        return doc.data().category;
      });
    })
    .catch(err => {
      console.log(err);
      return [1, 2, 3];
    });
}

And since you are using async/await already, you can rewrite this all to look like this so that your users can know when an error happened:并且由于您已经在使用 async/await,您可以将所有内容重写为如下所示,以便您的用户可以知道何时发生错误:

// notice the function is now async
async function getCategories() {
    const snapshot = await categories.get()
    // this can be a one-liner in the example above too
    return snapshot.map(doc => doc.data().category);
}

router.route("/categories").get(async function(req, res, next) {
   try {
     let arr = await getCategories();
     res.json(arr);
   } catch(ex) {
     res.status(500).json({ msg: ex.message });
   }
});

You are not returning your promise and value inside the .then .您不会在.then返回您的承诺和价值。 Add return in front of categories.get() call and return value inside then.categories.get()调用前添加return并在其中返回值。

getCategories needs to return a promise if you want to use await on it.如果你想在它上面使用awaitgetCategories需要返回一个 promise。 Right now, it's returning nothing.现在,它什么也没有返回。 You'll need to return the promise that you created:您需要返回您创建的承诺:

function getCategories() {
  let arr = [];
  return categories
    .get()
    .then(snapshot => {
      snapshot.forEach(doc => {
        console.log(doc.data().category);
        arr.push(doc.data().category);
        return arr;
      });
    })
    .catch(err => {
      console.log(err);
      return [1, 2, 3];
    });
}

Note the return keyword.请注意return关键字。

You also possibly have another problem here.您也可能在这里遇到另一个问题。 You're iterating the snapshot using forEach , and returning arr from within the lambda function that you passed to forEach .您正在使用forEach迭代快照,并从传递给forEach的 lambda 函数中返回arr This will not return the snapshot data to the caller.这不会将快照数据返回给调用者。 You will need to return a value from the then lambda:您将需要从返回一个值, then拉姆达:

    .then(snapshot => {
      const arr = []
      snapshot.forEach(doc => {
        console.log(doc.data().category);
        arr.push(doc.data().category);
      });
      return arr;
    })

You can try something like this :你可以尝试这样的事情:

function getCategories() {
  let arr = [];
  categories
    .get()
    .then(snapshot => {
      snapshot.forEach(doc => {
        console.log(doc.data().category);
        arr.push(doc.data().category);
        });
        console.log('arr',arr); //check the array data
        return arr;
    })
    .catch(err => {
      console.log(err);
      return [1, 2, 3];
    });
}

router.route("/categories").get(async function(req, res, next) {
  let arr = await getCategories().catch(err => {
         res.status(400).send(err);
   });
  res.json(arr);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM