Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用Express从一个端点发送多个查询?_Javascript_Node.js_Rest_Express - Fatal编程技术网

Javascript 如何使用Express从一个端点发送多个查询?

Javascript 如何使用Express从一个端点发送多个查询?,javascript,node.js,rest,express,Javascript,Node.js,Rest,Express,我试图多次查询我的数据库,并构造一个对象,将数据库中的每个响应存储在一个字段中。这是我的密码: router.post('/search', (req, res) => { var collection = db.get().collection('styles') var data = []; collection.distinct('make.name', (err, docs) => { data.push({'make': docs })

我试图多次查询我的数据库,并构造一个对象,将数据库中的每个响应存储在一个字段中。这是我的密码:

router.post('/search', (req, res) => {
    var collection = db.get().collection('styles')
    var data = [];

    collection.distinct('make.name', (err, docs) => {
      data.push({'make': docs });
    });

    collection.distinct('model', (function (err, docs) {
        data.push({'model': docs });
    }))

    res.send(data);
});

因为NodeJS/Express是异步的,所以它不能像我希望的那样工作。如何重建此端点以进行多个数据库调用(来自同一集合)并返回包含它的对象?

有多种方法:

嵌套回调 如果没有承诺,您可以嵌套回调:

router.post('/search', (req, res) => {
    var collection = db.get().collection('styles')
    var data = [];

    collection.distinct('make.name', (err, docs) => {
      if (err) {
        // ALWAYS HANDLE ERRORS!
      }
      data.push({'make': docs });
        collection.distinct('model', (function (err, docs) {
          if (err) {
            // ALWAYS HANDLE ERRORS!
          }
          data.push({'model': docs });
          res.send(data);
        }))
    });
});
这是最简单的方法,但请注意,如果这两个请求可以并行执行,则效率低下

async
模块 您可以使用
async
模块:

router.post('/search', (req, res) => {
    var collection = db.get().collection('styles')
    var data = [];

    async.parallel({
      make: cb => collection.distinct('make.name', cb),
      model: cb => collection.distinct('model', cb),
    }, (err, responses) => {
      if (err) {
        // ALWAYS HANDLE ERRORS!
      }
      data.push({'make': responses.make });
      data.push({'model': responses.model });
      res.send(data);
    });
});
见:

但这可能仍然不是最方便的方法

ES2017
async
/
wait
如果你有30个电话要打,最灵活的方法是:

  • 使用返回承诺的函数,而不是接受回调的函数
  • 如果可以,请使用async/await,或者至少使用基于生成器的协同路由
  • 当逻辑需要按顺序运行时,等待承诺(或收益承诺)
  • 使用
    Promise.all()
  • 使用async/await,您的代码可能如下所示:

        // in sequence:    
        var make = await collection.distinct('make.name');
        var model = await collection.distinct('model');
        // use 'make' and 'model'
    
    或:

    async
    /
    await
    的一大优点是错误处理:

    try {
      var x = await asyncFunc1();
      var array = await Promise.all([asyncFunc2(x), asyncFunc3(x)]);
      var y = asyncFunc4(array);
      console.log(await asyncFunc5(y));
    } catch (err) {
      // handle any error here
    }
    
    只能在使用
    async
    关键字创建的函数中使用它。有关详细信息,请参阅:

    有关浏览器中的支持,请参阅:

    有关节点中的支持,请参阅:

    在本机不支持
    async
    wait
    的地方,可以使用Babel:

    或者使用稍微不同的语法,使用基于生成器的方法,如
    co
    或Bluebird协同程序:

    有关更多信息,请参见这些答案:


    实现这一点的方法不止一种:

    嵌套回调 如果没有承诺,您可以嵌套回调:

    router.post('/search', (req, res) => {
        var collection = db.get().collection('styles')
        var data = [];
    
        collection.distinct('make.name', (err, docs) => {
          if (err) {
            // ALWAYS HANDLE ERRORS!
          }
          data.push({'make': docs });
            collection.distinct('model', (function (err, docs) {
              if (err) {
                // ALWAYS HANDLE ERRORS!
              }
              data.push({'model': docs });
              res.send(data);
            }))
        });
    });
    
    这是最简单的方法,但请注意,如果这两个请求可以并行执行,则效率低下

    async
    模块 您可以使用
    async
    模块:

    router.post('/search', (req, res) => {
        var collection = db.get().collection('styles')
        var data = [];
    
        async.parallel({
          make: cb => collection.distinct('make.name', cb),
          model: cb => collection.distinct('model', cb),
        }, (err, responses) => {
          if (err) {
            // ALWAYS HANDLE ERRORS!
          }
          data.push({'make': responses.make });
          data.push({'model': responses.model });
          res.send(data);
        });
    });
    
    见:

    但这可能仍然不是最方便的方法

    ES2017
    async
    /
    wait
    如果你有30个电话要打,最灵活的方法是:

  • 使用返回承诺的函数,而不是接受回调的函数
  • 如果可以,请使用async/await,或者至少使用基于生成器的协同路由
  • 当逻辑需要按顺序运行时,等待承诺(或收益承诺)
  • 使用
    Promise.all()
  • 使用async/await,您的代码可能如下所示:

        // in sequence:    
        var make = await collection.distinct('make.name');
        var model = await collection.distinct('model');
        // use 'make' and 'model'
    
    或:

    async
    /
    await
    的一大优点是错误处理:

    try {
      var x = await asyncFunc1();
      var array = await Promise.all([asyncFunc2(x), asyncFunc3(x)]);
      var y = asyncFunc4(array);
      console.log(await asyncFunc5(y));
    } catch (err) {
      // handle any error here
    }
    
    只能在使用
    async
    关键字创建的函数中使用它。有关详细信息,请参阅:

    有关浏览器中的支持,请参阅:

    有关节点中的支持,请参阅:

    在本机不支持
    async
    wait
    的地方,可以使用Babel:

    或者使用稍微不同的语法,使用基于生成器的方法,如
    co
    或Bluebird协同程序:

    有关更多信息,请参见这些答案:


      • 你可以通过承诺来实现

        router.post('/search', (req, res) => {
            var collection = db.get().collection('styles');
            // Create promise for "make.name" query
            let firstQuery = new Promise((resolve, reject) => {
                collection.distinct('make.name', (err, docs) => {
                    if (!err) {
                        resolve(docs);
                    } else {
                        reject(err);
                    }
                });
            });
            // Create promise for "model" query
            let secondQuery = new Promise((resolve, reject) => {
                collection.distinct('model', (function (err, docs) {
                    if (!err) {
                        resolve(docs);
                    } else {
                        reject(err);
                    }
                }))
            })
            // Run both queries at the same time and handle both resolve results or first reject
            Promise.all([firstQuery, secondQuery])
                .then((results) => {
                    res.send({ "make.name": results[0], "model": results[1] });
                })
                .catch((err) => {
                    // Catch error 
                    res.send({});
                });
        });
        
        此外,您还可以在回调函数中使用分解,如下所示:

        Promise.all([firstQuery, secondQuery])
            .then(([makeName, model]) => res.send({ "make.name": makeName, model }))
        
        UPD:如果要请求一组集合,可以创建一个集合名称数组,将其映射到promise请求并使用promise.all进行处理

        let collections = ["firstCollection", "secondCollection", "nCollection"];
        let promises = collections.map((collectionName) => {
            return new Promise((resolve, reject) => {
                collection.distinct(collectionName, (err, docs) => {
                    if (!err) {
                        resolve(docs)
                    } else {
                        reject(err);
                    }
                });
            })
        });
        Promise.all(promises)
            .then(results => {
                // Do what you want to do
            })
            .catch(error => {
                // or catch 
            });
        

        你可以通过承诺来做到

        router.post('/search', (req, res) => {
            var collection = db.get().collection('styles');
            // Create promise for "make.name" query
            let firstQuery = new Promise((resolve, reject) => {
                collection.distinct('make.name', (err, docs) => {
                    if (!err) {
                        resolve(docs);
                    } else {
                        reject(err);
                    }
                });
            });
            // Create promise for "model" query
            let secondQuery = new Promise((resolve, reject) => {
                collection.distinct('model', (function (err, docs) {
                    if (!err) {
                        resolve(docs);
                    } else {
                        reject(err);
                    }
                }))
            })
            // Run both queries at the same time and handle both resolve results or first reject
            Promise.all([firstQuery, secondQuery])
                .then((results) => {
                    res.send({ "make.name": results[0], "model": results[1] });
                })
                .catch((err) => {
                    // Catch error 
                    res.send({});
                });
        });
        
        此外,您还可以在回调函数中使用分解,如下所示:

        Promise.all([firstQuery, secondQuery])
            .then(([makeName, model]) => res.send({ "make.name": makeName, model }))
        
        UPD:如果要请求一组集合,可以创建一个集合名称数组,将其映射到promise请求并使用promise.all进行处理

        let collections = ["firstCollection", "secondCollection", "nCollection"];
        let promises = collections.map((collectionName) => {
            return new Promise((resolve, reject) => {
                collection.distinct(collectionName, (err, docs) => {
                    if (!err) {
                        resolve(docs)
                    } else {
                        reject(err);
                    }
                });
            })
        });
        Promise.all(promises)
            .then(results => {
                // Do what you want to do
            })
            .catch(error => {
                // or catch 
            });
        

        你应该使用承诺。@SLaks,我理解承诺的概念,但我从来没有实践过。如果您可以发布代码示例,我会将您的答案标记为正确。您应该使用承诺。@SLaks,我理解承诺的概念,但我从未应用过承诺。如果你能发布一个代码示例,我会把你的答案标记为正确的;它们不仅是有条件的,而且会有嵌套的噩梦。我欣赏你的方法,但是,它不够有效。我正在尝试为我的站点上可用的刻面搜索函数获取参数。@对于复杂代码,最灵活的解决方案是异步/等待或基于生成器的协同路由。看看我最新的答案。我有大约30个不同的电话要打;它们不仅是有条件的,而且会有嵌套的噩梦。我欣赏你的方法,但是,它不够有效。我正在尝试为我的站点上可用的刻面搜索函数获取参数。@对于复杂代码,最灵活的解决方案是异步/等待或基于生成器的协同路由。查看我的更新答案。您能解释结果[0]和结果[1]之间的差异吗?接下来是什么。。结果[2]。。。“n次呼叫的结果[n]?@Moshe确定。在
        Promise.all
        函数中有一个承诺数组。因此,在
        中,然后在
        Promise的
        中。所有
        处理程序都有一个参数数组,在每个
        Promise
        输入数组中传递给
        resolve
        回调函数,其顺序与它们在输入数组中的顺序相同,以便于澄清!你能解释一下结果[0]和结果[1]之间的区别吗?接下来是什么。。结果[2]。。。“n次呼叫的结果[n]?@Moshe确定。你有一个P的数组