使用promise的节点异步GET请求出现问题

Trouble with node asynchronous GET request using promises

本文关键字:请求 问题 GET 异步 promise 节点 使用      更新时间:2023-09-26

我刚开始编程(3个月),在节点如何处理异步函数方面遇到了问题(我想)。

我有一个方法为"addMenu"的Merchant类对象,该对象从外部API请求获取菜单,然后通过将Merchant.data.menu对象(默认为空)设置为我们刚刚获得的新菜单来更新商家。

有问题的代码:

this.addMenu = function(currentMerchant) {
  var id = currentMerchant.id;
  function  getMenu(id) {
    var deferred = Q.defer();
    var url = 'https://api.delivery.com/merchant/'+id+'/menu?client_id=xyz';
    request.get(url, function(error, response, body) {
      if(error) {
        console.log("Something went wrong with menu GET request: Status Code: " + response.statusCode);
        deferred.reject(new Error(error));
      } else if(!error && response.statusCode == 200) {
        menuObj = JSON.parse(body);
        deferred.resolve(menuObj);
      }        
    });
    return deferred.promise;
  };
  this.data.menu  = getMenu(id).then(function(currentMenu) {
    return currentMenu;
  });
  console.log(this.data.menu);
};

当我登录(this.data.menu)时,我会得到"{state:‘pending’}"。我可以执行setTimeout并使事情正常工作,但这不是违背了承诺的全部目的吗?我已经被这个普遍的问题困扰了好几天了——一直在研究回调、延迟、承诺等问题来解决它,但我想我可能在思考中错过了一些更基本的东西。

谢谢!

编辑以添加

毕竟,我意识到我问题的真正症结在于无法从回调/承诺内部访问this.data.menu,这导致我做了各种奇怪的事情,并试图将它们返回到this中。变量等

只需阅读"var that=this;"技巧即可访问类范围,这使我所有的回调和promise尝试都很好,在我的脑海中变得更有意义。我现在对我曾经打算作为附带利益的承诺有了更多的了解。谢谢大家的帮助!

then方法的返回仍然是一个承诺,因此不会实现。这是一个很难让你一开始就清醒过来的模式。(曾经玩过门户网站吗?:))

我想你想做一些类似的事情

getMenu(id).then(function(currentMenu) {
    this.data.menu  = currentMenu;
});

其中的关键部分是在实现承诺时调用的函数中执行任务。

除此之外的任何代码都不能保证在promise返回后运行(这就是为什么您得到控制台输出)

您也可以使用bluebird来承诺请求并执行以下操作:

var Promise = require('bluebird');
var getRequest = Promise.promisify(require('http').get);
this.addMenu = function(currentMerchant) {
  var id = currentMerchant.id;
  function  getMenu(id) {
    var deferred = Q.defer();
    var url = 'https://api.delivery.com/merchant/'+id+'/menu?client_id=xyz';
    return getRequest(url);
  }
  this.data.menu  = getMenu(id)
                      .then(function(response) {
                        return JSON.parse(response.body);
                      })
                      .catch(function (err){
                        console.log("Something went wrong with menu GET request: " + err);
                      });
  console.log(this.data.menu);
};