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

2024-01-12

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

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);
        }))
    });
});

这将是最简单的方法,但请注意,如果这两个请求可以并行完成,则效率不高。

The async module

您可以使用async module:

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);
    });
});

See: https://caolan.github.io/async/docs.html#parallel https://caolan.github.io/async/docs.html#parallel

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

ES2017 async/await

如果您要拨打 30 个电话,最灵活的方法是:

  1. 使用返回 Promise 的函数而不是接受回调的函数
  2. 如果可以或者至少使用基于生成器的协程,请使用 async/await
  3. 当逻辑需要按顺序运行时,等待 Promise(或 Yield Promise)
  4. Use Promise.all()对于任何可以并行完成的事情

使用 async/await 你的代码可能如下所示:

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

Or:

    // in parallel:
    var array = await Promise.all([
      collection.distinct('make.name'),
      collection.distinct('model'),
    ]);
    // use array[0] and array[1]

一个很大的优点是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关键词。有关更多信息,请参阅:

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

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

  • http://caniuse.com/async-functions http://caniuse.com/async-functions

有关 Node 中的支持,请参阅:

  • http://node.green/#ES2017-features-async-functions http://node.green/#ES2017-features-async-functions

在没有本地支持的地方async and await你可以使用巴贝尔:

  • https://babeljs.io/docs/plugins/transform-async-to-generator/ https://babeljs.io/docs/plugins/transform-async-to-generator/

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

  • https://www.npmjs.com/package/co https://www.npmjs.com/package/co
  • http://bluebirdjs.com/docs/api/promise.coroutine.html http://bluebirdjs.com/docs/api/promise.coroutine.html

请参阅这些答案以获取更多信息:

  • 带有 async/await 的 try/catch 块 https://stackoverflow.com/questions/40884153/try-catch-blocks-with-async-await/40886720#40886720
  • node.js ~ 构造 Promise 解析的链式序列 https://stackoverflow.com/questions/43238039/node-js-constructing-chained-sequence-of-promise-resolves/43238119#43238119
  • 如何并行运行生成器函数? https://stackoverflow.com/questions/42768461/how-to-run-generator-functions-in-parallel/42768639#42768639
  • node.js ~ 构造 Promise 解析的链式序列 https://stackoverflow.com/questions/43238039/node-js-constructing-chained-sequence-of-promise-resolves/43238119#43238119
  • 使用 async/await + Bluebird 来 promisifyAll https://stackoverflow.com/questions/43096728/using-async-await-bluebird-to-promisifyall/43096840#43096840
  • jQuery:ajax调用成功后返回数据 https://stackoverflow.com/questions/5316697/jquery-return-data-after-ajax-call-success/5316805#5316805
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Express 从一个端点发送多个查询? 的相关文章

随机推荐