使用promises

时间:2015-11-12 22:56:47

标签: javascript node.js asynchronous q npm-request

我对编程非常陌生(3个月),并且遇到节点处理异步函数的问题(我认为)。

我有一个带有方法的商家类对象" addMenu"从外部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' }&#34。我可以做setTimeout并让事情发挥作用,但这并没有打败承诺的全部目的吗?我已经被困在这个普遍的问题上好几天了 - 已经深入研究回调,延迟,承诺等解决它,但我想我可能会遗漏一些更为根本的想法。

谢谢!

编辑以添加

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

只需阅读" var that = this;"获得访问类范围的技巧,这使得我的所有回调和承诺尝试都能正常工作,让我的头脑更有意义。而且我现在知道更多关于我曾打算作为附带利益的承诺。谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

从then方法返回仍然是一个承诺,所以不会实现。这是一个很难理解的范例。 (曾玩门户?:))

我想你想做这样的事情

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

这个的关键部分是你在履行承诺时调用的函数内部进行赋值。

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

答案 1 :(得分:-1)

您还可以使用bluebird来宣传请求,并执行以下操作:

Sub Angie()

    Dim i&, j&, k&, v, w, x

    With Sheets("a"): v = .[a1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row): End With
    With Sheets("b"): w = .[a1].Resize(.Cells(.Rows.Count, 1).End(xlUp).Row): End With

    ReDim x(1 To UBound(v) * UBound(w), 1 To 2)
    x(1, 1) = v(1, 1): x(1, 2) = w(1, 1)

    k = 1
    For i = 2 To UBound(v)
        For j = 2 To UBound(w)
            k = k + 1
            x(k, 1) = v(i, 1)
            x(k, 2) = w(j, 1)
        Next
    Next
    Sheets("a").[c1:d1].Resize(UBound(x)) = x

End Sub