【问题标题】:How to handle a request with node/express that requires two asynchronous methods如何使用需要两个异步方法的 node/express 处理请求
【发布时间】:2013-12-11 23:00:13
【问题描述】:

我正在学习节点。我有一个通过bitcoin 包与bitcoind 连接的Web 应用程序,以及通过knex 与PostgreSQL 连接的Web 应用程序。我需要从每个模块中获取一些数据,然后将其全部传递给我的视图进行渲染。到目前为止,我的代码如下所示:

exports.index = function(req, res){
  var testnet='';
  bitcoin.getInfo(function(e, info){
    if(e){ return console.log(e);}
    if(info.testnet){
      testnet='bitcoin RPC is testnet';
    }else{
      testnet='nope.. you must be crazy';
    }
    var c=knex('config').select().then(function(k){
      res.render('index', { title: k[0].site_name, testnet: testnet });
    });
  });
};

虽然这种结构的方式是,它会首先等待比特币回复,然后它会向 PostgreSQL 发出请求,然后再等待一段时间让它回复。这两个等待期显然可以同时发生。但是,我不知道如何使用 Javascript 中的承诺/回调来做到这一点。我怎样才能让它异步发生,而不是串行发生?

【问题讨论】:

  • 您对 Postgre 的请求是否依赖于比特币的响应?
  • @r3mus 并非总是如此。有时可以并行
  • 如果不是,那么乔的答案绝对是要走的路。如果它确实回复了响应,那么您将无法运行这些异步。

标签: javascript node.js asynchronous promise


【解决方案1】:

您正在寻找async 模块,它可以让您启动两个任务然后继续。

一个未经测试的例子给你的想法:

exports.index = function(req, res){
    var testnet='', k={};

    async.parallel([
      function(){ 
        bitcoin.getInfo(function(e, info){
          //your getInfo callback logic
           },
      function(){
        knex('config').select().then(function(result) {       
         //your knex callback
         k = result;
      } ],
      //Here's the final callback when both are complete
      function() {
         res.render('index', { title: k[0].site_name, testnet: testnet });
      });
}

【讨论】:

  • 实现这项工作的实际代码要复杂得多,尤其是在错误处理方面:/
  • 顺便说一句,为了将来参考,这是我对我的代码所做的相关提交。值得注意的是,每个并行任务都必须接受并调用一个回调函数来指示它已完成。 github.com/Earlz/d4btc/commit/…
【解决方案2】:

您可以使用像 caolan/async#parallel() 方法这样的库,或者您可以探索它的源代码并学习扮演自己的角色

【讨论】:

    【解决方案3】:

    你需要承诺回调方法,而不是混合回调和承诺。

    var Promise = require("bluebird");
    var bitcoin = require("bitcoin");
    //Now the bitcoin client has promise methods with *Async postfix
    Promise.promisifyAll(bitcoin.Client.prototype);
    
    var client = new bitcoin.Client({...});
    

    然后是实际代码:

    exports.index = function(req, res) {
        var info = client.getInfoAsync();
        var config = knex('config').select();
    
        Promise.all([info, config]).spread(function(info, config) {
            res.render('index', {
                title: config[0].site_name,
                testnet: info.testnet ? 'bitcoin RPC is testnet' : 'nope.. you must be crazy'
            });
        }).catch(function(e){
            //This will catch **both** info and config errors, which your code didn't
            //do
            console.log(e);
        });
    };
    

    使用了 Promise 模块 bluebird

    【讨论】:

    • 这很有趣。我不知道 Promisify,也不知道当它都是 Promisify 时代码有多优雅
    • @Earlz 是的,将结果作为普通变量中的值真的很棒
    猜你喜欢
    • 2016-06-16
    • 2019-02-07
    • 2019-03-19
    • 2020-12-31
    • 1970-01-01
    • 2016-08-21
    • 2021-02-18
    • 2015-02-22
    • 2020-12-20
    相关资源
    最近更新 更多