2012-05-05 29 views
0

我正在使用Redis爲我的內存存儲模型生成ID。 Redis的客戶端需要一個回調到INCR命令,這意味着代碼看起來像如何在Node.js中同步處理回調?

client.incr('foo', function(err, id) { 
    ... continue on here 
}); 

的問題是,我已經寫的應用程序的其他部分,即預計incr調用是同步的,只是返回的ID,這樣我可以使用它像

var id = client.incr('foo'); 

爲什麼我對這個問題的原因是,到現在爲止,我正在生成的ID只是一個簡單的封閉計數器功能的記憶,就像

var counter = (function() { 
    var count = 0; 
    return function() { 
    return ++count; 
    } 
})(); 

簡化測試,只是一般的設置。

這是否意味着我的應用程序設計有瑕疵,我需要重寫它期望在生成ID的回調?還是有什麼簡單的方法來同步呼叫?

+0

我不認爲這會對你有所幫助,但我已經看到了,並且不需要回調。 https://github.com/mranney/node_redis搜索'「client.set(」foo'和'client.incr(「做了一件事)」;' –

+0

@MiaDiLorenzo只有當你想忽略返回值時,你可以很容易地爲'set'做,但不是'incr',你實際上唯一需要的是遞增的值:) –

+0

噢,我現在明白了。否則,你將不得不分別寫一個需要回調的get。 –

回答

3

Node.js本質上是一個異步I/O庫(帶插件)。因此,根據定義,那裏沒有同步I/O,您應該重寫您的應用程序。

2

這是一個有點痛,但你必須做的是包裝,你有計數器產生進入功能後,並調用從Redis的回調邏輯。如果你有這樣的事情:

var id = get_synchronous_id(); 
processIdSomehow(id); 

你需要做這樣的事情。

var runIdLogic = function(id){ 
    processIdSomehow(id); 
} 

client.incr('foo', function(err, id) { 
    runIdLogic(id); 
}); 

你需要適當的錯誤檢查,但類似的東西應該爲你工作。

有用於節點一對夫婦順序編程層(如TameJS),可能會幫助你想要的東西,但這些一般做重新編譯或類似的事情:你要決定你是多麼舒服,如果你想使用它們。

0

@Sergio說,這短暫在他的答案,但我想寫多一點擴大的答案。 node.js是一個異步設計。它運行在一個單獨的線程中,這意味着爲了保持快速並處理許多併發操作,所有阻塞調用都必須對其返回值進行回調,以便異步運行它們。

這並不意味着同步調用是不可能的。他們是,而且它是你如何信任第三方插件的關注。如果有人決定在他們的插件中寫入一個阻止的調用,那麼你就受到這個調用的支配,它甚至可能是內部的東西,而不是暴露在他們的API中。因此,它可以阻止你的整個應用程序。考慮一下,如果Redis花費大量時間返回,可能會發生什麼情況,然後由可能訪問相同例程的客戶端數量來多次發生。整個邏輯已經序列化,他們都在等待。

在回答你的最後一個問題,你不應該對容納阻止機制工作。它現在看起來可能是一個簡單的解決方案,但它首先與node.js的優點相反。如果您只是在同步設計工作流程中感覺更舒適,那麼您可能需要考慮以此方式設計的另一個框架(使用線程)。如果您想堅持使用node.js,請重寫您的現有邏輯以符合回調風格。從我看到的代碼示例中,它看起來像一個嵌套的函數集,因爲回調函數使用回調函數等,直到它可以從遞歸堆棧中返回。

0

node.js中的應用程序狀態通常作爲對象傳遞。我會做的更接近:

var state = {} 

client.incr('foo', function(err, id) { 
    state.id = id; 
    doSomethingWithId(state.id); 
}); 

function doSomethingWithId(id) { 
    // reuse state if necessary 
} 

這只是一種不同的做事方式。