將res.json(req.body);
移動到回調函數中。
除了範圍問題:它是異步的,所以在你的代碼中,它將在res.json(req.body)
運行後被調用很長時間。
app.get('/api/etsy/getListings', function(req, res) {
bEtsy.getAllListings(req, res, function(err, body) {
res.json(body);
//console.log(body);
});
});
手頭一個更普遍的忠告(或兩個或三個)的,除了問題:
什麼幫助我這樣的情況,「回調思考」是幾乎從不使用內聯回調函數:只編寫一層深的代碼(當然加上一層模塊模式),避免回調地獄!命名所有回調並將它們全部寫入相同(頂部)級別。
function allListingsReceived(err, body, res) {
res.json(body);
//console.log(body);
}
function getListings(req, res) {
// ASYNC
bEtsy.getAllListings(req, res, allListingsReceived);
}
//ASYNC
app.get('/api/etsy/getListings', getListings);
這使我能夠更好地瞭解實際的呼叫順序。在這種情況下,當getAllListings
被調用時,你知道它是異步的 - 在我自己的代碼中添加一個明確的註釋(就像我上面所做的那樣)。所以我知道我寫的東西之後,異步函數將無法訪問任何異步函數應該給我的東西。恕我直言,這樣的評論是重要 - 在JavaScript中沒有辦法知道回調函數是否異步。通常情況下,如果它是同步的並且你期望異步,你也可能會陷入困境!所以我認爲最好把它寫成註釋(在整個項目中總是使用完全相同的短字符串),這是一個形式化的代碼註釋。順便提一下,當您編寫接受回調函數的函數時,請確保它們總是以同步或異步方式調用它,而不是兩種方式(一些函數使用緩存值並能夠立即返回結果而不是啓動異步網絡請求)。
基本上,書面結構並不能反映這種風格的運行時情況 - 但這是可以的,因爲無論如何運行時情況是完全靈活的(如果你想改變你使用的回調函數,或者增加另一個回調函數之間,你是否真的想要轉換大量的代碼行,而不是僅僅交換一個名字?更不用說增加了可重用性的易用性)。這更容易閱讀更長的回調式代碼文件,然後幾層深嵌套異步函數恕我直言。儘可能避免功能內部的功能,除了模塊模式。
具有命名函數也更適合調試,堆棧跟蹤更容易閱讀。
的說明:我的示例代碼留下一個問題開:如果這是一個模塊(或類)內,這些將是內部的功能,你可能必須確保對正確的上下文/範圍(其中this
點,如果你從這些函數內部以這種方式訪問對象成員變量)。當這些功能在原型上時,它的工作原理是一樣的。所以這只是一個概念的例子,無視這個問題。
另一個注意事項:在調用回調函數時,現在必須使用以前可用於內部函數的內部函數(在本示例中爲res
)時寫入此樣式變量。這增加了一些複雜性 - 但另一方面迫使您在自己的代碼中創建乾淨的(er)API。就我個人而言,我不喜歡過度依賴封閉來傳遞論據。我太愚蠢了,我更喜歡通過讓一個函數在其標題中使用的所有參數來定義一個乾淨的接口定義。顯然我並不孤單,這是功能性編程最常被吹捧的優點之一:)另外一種替換爲「乾淨」參數的標題也是this
下的對象屬性。我的小例子看起來有點「程序性」,但它只是用來說明一個問題。當然,這屬於模塊化編程的更大範圍。
哇,可以發誓我曾試過,但我猜不是。謝謝! :) – ReganPerkins
非常感謝你的額外信息!對不起,我不得不再等幾分鐘來申報和回答,但非常感謝你花了這麼多時間,這有助於很多:) – ReganPerkins
@XxscurvyxX面對「思維異步」困難的Javascript編碼風格 - 我最喜歡的一種主題,我的榮幸:) –