2017-02-16 4 views
-2

私は、HTTP経由でクライアントからのREST呼び出しを処理するnodejsアプリケーション(expressを使用しています)を開発しています。 REST APIの1つがPOST要求を処理し、POST本体からデータを取り出し、MQTTクライアントを介して公開します(アプリケーションの一部として開始されます)。JavaScriptで別々のコールバックを同期する方法

私が発行したトピックにサブスクライブされている(MQTTブローカー経由で)別のアプリケーションは、メッセージを受信し、アプリケーションのMQTTクライアントがサブスクライブしているトピックにメッセージを公開することによって応答します私のJavascriptアプリでトリガーするコールバック)。

私のアプリケーションが処理しているPOST応答で私のアプリケーションが受け取るMQTTメッセージを返すことができます。

通常の「C言語プログラミング」の用語では... REST APIを処理するスレッドと、MQTTメッセージを受信する別のスレッド(2つの異なるソケットなど)があります。 MQTTスレッドがいくつかのデータを受け取ってエンキューし、セマフォを解放してPOST処理スレッドのブロックを解除するまで、セマフォ上のPOST処理スレッドを処理するスレッドをブロックしたいとします(メッセージをデキューしてからPOST応答)。

これを行うには、「JavaScriptの道」とは何様々なモジュールとの約束/ジェネレータいじりの後、それを動作させるためにどのように私には明確ではない...

TIA!

+0

コードについての質問は、実際のコードを含めるべきです(SHOULD)。 – jfriend00

答えて

1

node.jsでブロックしません。それは非常に設計的なので、node.jsはイベント駆動型で、すべてのネットワークI/O(およびほとんどのファイルI/O)は非ブロッキングと非同期です。したがって、複数の非同期オペレーションを調整し、両方のイベントが終了したときに通知を受け取る必要があります(イベントの種類によって)。

あなたのコードを共有していないときは非常に具体的ではありませんが、今日の非同期操作を調整する主なツールは約束です。したがって、非同期操作が完了したときに解決する約束を返すか、または非同期操作でエラーが発生したときに却下する約束を返す場合は、Promise.all()を2つの約束と共に使用することができます。両方の結果を提供しています。

一般的な考えはこれです:RESTの事業からの約束を取得するための

let p1 = asyncOperation1(...); 
let p2 = asyncOperation2(...); 

Promise.all([p1, p2]).then(results => { 
    // both async operations are done here 
    // results[0] and results[1] contain the resolved value of each of the two promises 
}).catch(err => { 
    // process error here 
}); 

、手動で要求モジュールをラップモジュールに、あなたの業務を中心に、独自の約束ラッパーをやってから、様々な異なる解決策がいくつかありますBluebirdのような図書館には、.promisify().promisifyAll()の方法で自動的に操作がラップされるという約束をしてください。あなたの非同期操作から約束を得る方法に関するより具体的な情報を提供するには、実際のコードを共有する必要があります。


ここであなたが新しくなったように見えるので、投稿のアドバイスをしてください。あなたのコードを私たちに示すならば、私たちは常により完全でより適切な答えを提供することができます。あなたのコードを表示しないときは、基本的に、書くのがはるかに難しく、正確なユースケースをカバーするのをもっと難しくする汎用チュートリアルを求めています。

0

公開したメッセージに一意のIDを含めてブロックしないでください。応答メッセージにもこのIDが含まれています。

次に、このIDをキーとしてエクスプレス応答オブジェクトをオブジェクトに格納します。これは、応答があなたに到着して応答を返すときです。

待機中の応答オブジェクトを定期的に処理し、MQTTメッセージが到着しない場合に応答できるように、タイムスタンプも含める必要があります。

結局、私は解決策を考える上であったかもしれない考え出し
var onGoingRequests = {}; 
var id = 0; 

mqttClient.on('message',function(topic,message){ 
    var payload = JSON.parse(message.toString()); 
    var details = onGoingRequest[payload.id]; 
    if (details) { 
    details.response.status(200).send(details.body); 
    delete onGoingRequests[payload.id]; 
    } else { 
    //response too late 
    } 
}); 

app.post('/foo', function(req, resp) { 
    var message = { 
     id: 'foo' +id++, 
     body: req.body 
    } 
    var topic = 'request/foo'; 
    mqttClient.publish(topic, JSON.stringify(message)); 
    onGoingRequests[message.id] = { 
     response: resp, 
     timestamp: Date.now(), 
    }; 
}); 

var timeout = setInterval(function(){ 
    var now = Date.now(); 
    var keys = Object.keys(onGoingCommands); 
    for (key in keys){ 
    var waiting = onGoingCommands[keys[key]]; 
    if (waiting) { 
     var diff = now - waiting.timestamp; 
     if (diff < timeout) { 
     waiting.res.status(504).send('{"error": "timeout"}'); 
     delete onGoingCommands[keys[key]]; 
     } 
    } 
    } 
}, 500); 
1

...

私はレスポンスオブジェクトとリターンをエンキューPOST処理コールバックで。後で、MQTTサブスクライブ・メッセージ処理コールバックで、保留中の応答オブジェクトをデキューし、保留中のPOSTトランザクションに適切な応答を送信するためにそれを使用します。

+0

これは非常によく知られているように聞こえる... – hardillb

関連する問題