簡體   English   中英

如何與NodeJS同步運行兩個功能?

[英]How to run two functions synchronously with NodeJS?

我對NodeJS相當陌生,並且對異步機制一無所知。

我有一個代碼,應該將HTTP發布請求發送到第一個URL(例如-https://example.com/first ),然后在收到狀態代碼200答復時,將另一個請求發送到檢查該服務器的同一服務器如果服務器已處理完第一個請求(例如-https://example.com/statusCheck )。

服務器應該返回一個文本/純文本響應,如果繁忙則返回“ true”,如果准備就緒則返回“ false”。 我編寫了一個while循環,每2秒查詢一次服務器,最多進行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 yieldasync-await ,以避免發生回調地獄-在這種情況下,如何實現它們?

您應該使用Promise來做到這一點。 以下是一些使用bluebird的代碼,可以完成您想要的操作。 Promise.any方法將返回Array中10次嘗試中的第一個成功調用。

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));

您必須了解,異步操作在調用后不能立即返回結果。 它們執行后會觸發一些處理程序。 您可以/應該使用該入口點來啟動或繼續您​​的邏輯流程。

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

您可以使用異步庫。

您無需為此事做setInterval或任何計時器,只需等待響應即可。

具體來說,您可以為此使用async.waterfall,例如:

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)
  }
})

 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> 

在較新版本的nodejs中,您可以像上面的示例一樣使用async await

請注意,$。ajax不是節點函數。 只是為了示范

您可以在任何返回承諾的函數上使用await。 對於下一個示例,您需要安裝請求包並使用Node> = 8來使用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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM