1

我对编程非常陌生(3 个月)并且在节点如何处理异步函数方面遇到了麻烦(我认为)。

我有一个带有方法“addMenu”的 Merchant 类对象,它从外部 API 发出对菜单的 GET 请求,然后通过将 Merchant.data.menu 对象(默认为 null)设置为我们的新菜单来更新商家得到了。

有问题的代码:

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;” 访问类范围的技巧,这使我所有的回调和承诺尝试都可以正常工作,并且在我的脑海中变得更有意义。而且我现在知道了更多关于我曾经打算作为附带好处的承诺。感谢各位的帮助!

4

2 回答 2

1

then 方法的返回仍然是一个承诺,因此不会被履行。起初,这是一个很难理解的范例。(玩过传送门吗?:))

我想你想做这样的事情

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

这其中的关键部分是您在实现承诺时调用的函数内进行分配。

承诺返回后,不保证在此之外的任何代码都可以运行(这就是您获得该控制台输出的原因)

于 2015-11-12T23:13:42.263 回答
-1

您还可以使用 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);
};
于 2015-11-13T00:33:45.830 回答