【问题标题】:nodeJS / Express: what's wrong with this RSVP promise?nodeJS / Express:这个 RSVP 承诺有什么问题?
【发布时间】:2014-08-20 18:09:28
【问题描述】:

我正在使用 nodeJS,运行 express4 框架来创建 API。我正在使用 RSVP.js 进行承诺。

worker.getFamilies 由外部模块调用,此处未反映。调用者期望返回一个带有结果的对象。

worker.getFamilies 内部: - 我正在使用 mongoose 查询 mongoDB(有效,我们得到结果)

  • 我正在使用一个 promise 从 mongoose 获取可用的响应对象。这样可行。

  • 然后我尝试返回 JSON.stringify(results);给 worker.getFamilies 的调用者,这不起作用。调用者返回“未定义”。请帮忙。

    var worker = exports;
    var RSVP = require('rsvp');
    
    var getFamiliesFromDB = function(DBconnection){
        var promise = new RSVP.Promise(function(resolve, reject){
            DBconnection.find({} ,{limit:10, sort: [['_id',-1]]}).toArray(function(e, results){ 
                console.log('results:', results);
                resolve(results);
            });   
        });
        return promise;
    }
    
    worker.getFamilies = function(DBConnection){
        getFamiliesFromDB(DBConnection).then(function(results){
    
            //this works
            console.log('here are the fams from the promise', results);
    
            //this doesnt work like i want it to
            return JSON.stringify(results);
        });  
    };
    

【问题讨论】:

  • worker.getFamilies的调用者可以接受promise吗?如果没有,你必须强制请求是同步的。
  • 真的吗?在我看来,当我们返回 JSON.stringify(results); 时,承诺已经完成。我们现在不是只返回一个“正常”对象吗?
  • @quelquecosa The result of an asynchronous task can't really be returned. 此类任务是面向事件的,return 将在事件发生之前采取行动,或者在这种情况下,应用于回调 function(results) 而不是 worker.getFamilies() .
  • 回到worker.getFamilies内部:return getFamiliesFromDb(...)...

标签: javascript node.js express promise rsvp.js


【解决方案1】:

好吧,对于初学者来说,您的 worker.getFamilies 函数中没有单个 return 语句,这就是它返回 undefined 的原因(如果您没有明确返回,这就是 JavaScript 自动返回的内容)。

您唯一的回报是在 .then 处理程序中。你需要返回承诺:

worker.getFamilies = function(DBConnection){
    // note how we've added a `return` here!
    return getFamiliesFromDB(DBConnection).then(function(results){
        console.log('here are the fams from the promise', results);
        return JSON.stringify(results);
    });  
};

现在我们的函数返回了,我们可以使用它的返回值:

// from caller site:
worker.getFamilies(dbconn).then(function(jsonResults){
    console.log("Got results!", jsonResults);
});

【讨论】:

    【解决方案2】:

    正如 Jonathan Lonowski 解释的那样,"The result of an asynchronous task can't really be returned"

    对此有几个解决方案。

    如果您可以控制调用worker.getFamilies 的代码。您可以将代码修改为:

    worker.getFamilies = function(DBConnection){
        return getFamiliesFromDB(DBConnection).then(function(results) {
            return JSON.stringify(results);
        });  
    };
    

    使调用代码这样做:

    worker.getFamilies(DBConnection).then(function(results) {
      console.log('now I can work with', results);
    });
    

    如果你无法控制调用代码,它会变得稍微复杂一些:

    var data;
    worker.getFamilies = function() {
        return data;
    };
    getFamiliesFromDB(DBConnection).then(function(results) {
            data = JSON.stringify(results);
            // Here, start up the code where `worker.getFamilies` is used.
    });
    

    基本上,在调用需要它的代码之前,您需要确保结果已经准备好。

    【讨论】:

      【解决方案3】:

      问题是您从不同的上下文返回。重构getFamilies如下:

      worker.getFamilies = function(DBConnection, callback){
          getFamiliesFromDB(DBConnection).then(function(results){
              callback(JSON.stringify(results));
          });  
      };
      

      由于调用堆栈中至少有一个异步函数(在您的情况下 - getFamiliesFromDb),您需要回调(或承诺)。

      在您的版本中,您的 return 语句解析为回调函数,而不是您希望的 getFamilies

      另一种方法是将getFamiliesFromDB 转换为同步调用。要么使用 mongoose API,要么等待 promise 解析并返回它解析的数据。

      【讨论】:

      • 由于 OP 已经在使用 Promise,他不应该再次将它们降级为回调。
      猜你喜欢
      • 1970-01-01
      • 2017-05-08
      • 1970-01-01
      • 2019-06-20
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      • 2020-04-03
      • 2021-06-30
      相关资源
      最近更新 更多