2015-11-12 149 views
1

我很新編程(3個月),並且在節點處理異步函數(我認爲)時遇到問題。使用承諾節點異步GET請求的問題

我有一個Merchant類對象,它有一個方法「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),我得到 「{狀態: '掛起'}」。我可以setTimeout並讓事情發揮作用,但是這並不能擊敗promise的全部目的?我一直被困在這個一般性的問題上 - 一直在研究回調,延遲,承諾等來解決它,但我想我可能會錯過一些更重要的思想。

謝謝!

編輯補充

好以後的一切,我意識到,我的問題的真正關鍵是不能從回調/承諾內訪問this.data.menu導致我做的一切各種奇怪的東西,並試圖返回到這一點。變量等。

只需閱讀「var that = this;」欺騙獲得了類的範圍,這使得我所有的回調和承諾嘗試都能正常工作,並使我的頭腦更加有意義。我現在知道更多關於我曾經打算作爲副作用的承諾。感謝幫助人們!

+1

承諾不奇蹟般地使異步代碼同步。他們只能簡化我們對異步的處理。 – Bergi

回答

1

從當時的方法返回仍然是一個承諾,所以不會實現。首先,這是一個艱難的範例。 (打過門戶?:))

我想你想要做這樣的事情

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

這樣做的關鍵部分是你做的承諾被滿足時,被調用的函數內部分配。

的那個以外的任何代碼不能保證運行的承諾已回來後(這就是爲什麼你得到該控制檯輸出)

+0

看到這很有意義,並且是我最初設置的方式。但是我無法從.then函數回調中訪問'this.data.menu'。我想這就是我卡住的地方。如果我試圖暫時將它分配給addMenu方法中的一個變量,然後將其分配給'this.data.menu,它只會成功地將它粘貼在那裏,如果我添加一個延遲,所以我們又回到了一個...感謝您的幫助btw! – greenleaf

+0

看起來你現在正在掙扎的是這個回調的範圍。在那裏有很多帖子會解釋,比我可能做得更好。這是一個很普遍的問題,有些人主張不要使用這個和其他人不同意。它由你來決定。這裏是一個示例帖子http://weblogs.asp.net/dwahlin/working-with-the-javascript-this-keyword – ScottG

+0

謝謝ScottG,那正是我的問題......將研究'這'用法的理論 – greenleaf

-1

你也可以使用藍鳥到promisify請求,做這樣的事情:

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); 
}; 
+0

OP已經在使用Q. – Mathletics

+0

是的,這樣溝渠Q,並與圖書館,讓你promisify回調。他的問題不在於對承諾的理解,而在於對回調的混合承諾。 – tacotuesday

+0

不; OP已經正確設定了使用承諾的請求;問題在於他們錯誤地使用了返回值。切換庫不會有所作爲。看起來你的代碼遭受同樣的困惑。 – Mathletics