2017-08-02 5 views
0

私はNodeJSでかなり新しく、非同期メカニズムで失われました。NodeJSと同期して2つの関数を実行する方法は?

HTTP POST要求を最初のURL(たとえば、https://example.com/first)に送信するコードがあり、ステータスコード200で応答されたときに、同じサーバーに別の要求を送信してサーバーが存在するかどうかを確認します最初の要求の処理で完了します(たとえば、-https://example.com/statusCheck)。

サーバはテキスト/プレーンレスポンスを返します。ビジー状態の場合は「true」、使用準備ができている場合は「false」を返します。 私は、2秒ごとにサーバーに照会するwhileループを使用して書き込みました。最大で10回の反復までです。言い換えれば

var request = require('request'); 

var firstURL = "https://example.com/first"; 
var serverCheck = "https://example.com/statusCheck"; 

// Sends up to 10 requests to the server 
function checkServerStatus(){ 
    var serverReady = false; 
    var count = 0; 
    while (!serverReady && count < 10) { 
     count++; 
     setTimeout(function(){ 
      request.get(serverCheck, function(err, resp, body){ 
       if (err){ 
        console.log(err); 
       } else if (body == "false") { 
        generatorReady = true; 
       } 
      }) 
     }, 2000); 
    } 
    return generatorReady; 
} 

// Sends the first request and return True if the response equals to 200 
function sendFirstRequest(){ 
    var req = request.post(firstURL, function (err, resp, body) { 
     if (err) { 
      console.log(err); 
      return false; 
     } else if (resp.statusCode === 200){ 
      return true; 
     } else { 
      return false; 
     } 
    }); 
}; 


module.exports = function(){ 
    // Sends the first request 
    var firstRequestStatus = sendFirstRequest(); 
    if (firstRequestStatus) { 
     return checkServerStatus(); 
    } 
}; 

は、私は、sendFirstRequestが最初に実行応答を待つしたい、と応答がtrueである場合には、私がcheckServerStatusを実行して、彼の戻り値を取得したいです。反復中にそれぞれの間で睡眠をとることができれば、それは素晴らしいでしょう(setTimeoutは私にとってもうまくいきません)。

編集:コールバック地獄を避けるためにfunction* with yieldまたはasync-awaitを使用できると聞いてきましたが、この場合はどうすれば実装できますか?

+0

を使用するためのノード> = 8を使用する必要が次の例 。 [Example here](https://stackoverflow.com/questions/19739755/nodejs-callbacks-simple-example) – chrpk

+0

ノード8+を使用している場合は、Hi Dan、https://nodejs.org/apiをご覧ください/http.html#http_http_request_options_callback ---あなたの編集に関しては、ジェネレータ(関数* w/yield)を使用したいとは思っていません。また、http.requestモジュールでasync/awaitを使用する場合は、あなたがasync/awaitで動作させたい方法でそれを包むために '約束する'(これはすべての関数では当てはまりません)。この場合、私は約束事から始め、async/awaitに切り替えることを理解しています。 –

答えて

4

これを行うにはPromiseを使用する必要があります。以下は、あなたが望むことを行うbluebirdを使用しているコードです。 Promise.anyメソッドは、10回の試行のうち、Arrayから最初に成功した呼び出しを返します。

const Promise = require('bluebird'); 
var request = Promise.promisifyAll(require('request')); 

var firstURL = "https://example.com/"; 
var serverCheck = "https://example.com/statusCheck"; 

request.postAsync(firstURL).then(res => { 
    if (res.statusCode === 200) return true; 
    throw new Error('server not ready'); 
}).then(() => 
    Promise.any(new Array(10).fill(request.getAsync(serverCheck))) 
).then(res => { 
    console.log(res); 
}).catch(err => console.log(err)); 
1

非同期操作では、呼び出し直後に結果を返すことはできません。実行したときにハンドラをトリガします。ロジックフローを開始または継続するには、そのエントリポイントを使用することができます。

http.post(params, handler(err, resp, body){ 
     if(err){ 
     failFlow(err); 
     }else if(resp.statusCode === 200) { 
     successFlow(resp); 
     } 
}); 

、あなたが必要がありますが、あなたがこのようにレスポンスを返すことができないようチェーンなど多くのそのような非同期呼び出しをすることができます。

また、Promiseのコンセプトに興味があるかもしれません。

var request = require('request'); 
 

 
var firstURL = "https://example.com/first"; 
 
var serverCheck = "https://example.com/statusCheck"; 
 
var count = 0; 
 

 
// Sends up to 10 requests to the server 
 
function checkServerStatus() { 
 
    if (count++ > 10) return; 
 

 
    request.get(serverCheck, function(err, resp, body) { 
 
    if (err) { 
 
     console.log(err); 
 
     checkServerStatus(); 
 
    } else if (body == "false") { 
 
     // go further 
 
    } 
 
    }); 
 
} 
 

 
// Sends the first request and return True if the response equals to 200 
 
function sendFirstRequest(cb) { 
 
    var req = request.post(firstURL, function(err, resp, body) { 
 
    if (err) { 
 
     console.log(err); 
 
     return false; 
 
    } else if (resp.statusCode === 200) { 
 
     cb(); 
 
    } else { 
 
     return false; 
 
    } 
 
    }); 
 
}; 
 

 

 
module.exports = function() { 
 
    // Sends the first request 
 
    sendFirstRequest(checkServerStatus); 
 
};

+0

その場合、 '/ go further'セクションで値や何かを返すことはできますか? – Dan

+0

@ダンあなたは何が必要なのか、何が成功するかによってduccessFlowの中で何が必要であれ、何をして成功するかを決めることができます:)なぜ何かを返す必要がありますか? – bluehipy

+0

私の実際のコードでは、関数 'sendFirstRequest'は配列を繰り返し処理していて、この配列に存在するURLにリクエストを送ります。つまり、サーバーがビジー状態でないときはいつでも、 – Dan

0

あなたがasyncライブラリを使用することができます。

あなたはsetIntervalやそのようなタイマーを行う必要はありません。応答を待つだけです。

特にあなたがこのためにasync.waterfall使用することができ、何かのように:あなたは非同期を使用することができますnodejsの新しいバージョンで

var async = require('async') 
var request = require('request') 

async.waterfall([ 
    function(cb) { 
    // send the first request 
    request.post("https://example.com/first", function (err, resp) { 
     // send the response to the next function or break in case there was an error 
     cb(err, resp) 
    }) 
    }, 
    function(resp, cb) { 
    // check for the response 
    if (resp.statusCode === 200) { 
     // in case the response code is 200 continue to the next function 
     return cb() 
    } 

    // if its not 200 break with the response code as an error 
    return cb(resp.statusCode) 
    }, 
    function(cb) { 
    // send the verify 
    request.get("https://example.com/statusCheck", function (err, resp, body) { 
     // send the body of the response to the next function or break in case of an error 
     cb(err, body) 
    }) 
    } 
], function (err, result) { 
    // check if there was an error along the way 
    if (err) { 
    console.log("there was an error", err) 
    } else { 
    // all is good print the result 
    console.log("result:", result) 
    } 
}) 
0

async function main() { 
 
    console.log('First call started'); 
 
    let response1 = await $.ajax({url: "https://api.stackexchange.com/2.2/questions/269754/answers/?order=desc&site=meta.stackoverflow&client_id=3519&callback=?"}) 
 
    console.log('First call finished', response1); 
 
    console.log('Second call started'); 
 
    let response2 = await $.ajax({url: "https://api.stackexchange.com/2.2/questions/269754/answers/?order=desc&site=meta.stackoverflow&client_id=3519&callback=?"}) 
 
    console.log('Second call finished',response2); 
 
} 
 

 
main();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

上記の例のように待っています

$ .ajaxはノード関数ではないことに注意してください。デモンストレーションのためだけです

約束を返す関数であれば、awaitを使用できます。あなたが要求パッケージをインストールし、あなたがコールバックを使用してそれを行うことができますpromisify

const {promisify} = require('util'); 
const request = require('request') 

async function main() { 
    let get = promisify(request); 
    let response1 = await get('https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain&rnd=new'); 
    console.log('first random: ',response1.body) 
    let response2 = await get('https://www.random.org/integers/?num=1&min=1&max=100&col=1&base=10&format=plain&rnd=new'); 
    console.log('second random: ',response2.body) 
} 

main(); 

http://2ality.com/2017/05/util-promisify.html

https://github.com/request/request

+0

jQuery以外のAJAXジェネレータを使用する場合は問題はありますか? – Dan

+0

それは問題ではありません。約束を返すものは何でもOKです。私は答えの例を追加しました –

関連する問題