我对NodeJS很新,并且迷失了异步机制。
我有一个代码应该向第一个URL发送HTTP post请求(例如 - https://example.com/first),然后当它得到状态代码200的回答时,向同一个服务器发送另一个请求,检查是否服务器完成处理第一个请求(例如 - https://example.com/statusCheck)。
服务器应该返回一个text / plain响应包含" true"如果它很忙,"假"如果它准备好了。 我用一个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 yield
或async-await
来避免回调地狱 - 在这种情况下如何实施?
答案 0 :(得分: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 :(得分: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);
};
&#13;
答案 2 :(得分:0)
您可以使用async库。
你不需要为此做一个setInterval或任何计时器,只需等待响应。
具体来说,您可以使用async.waterfall,例如:
<div class="container">
<h2>Select a Console</h2>
<div class="col-lg-4 consoleRed">
<div class="consoleIcon"><img width="64" height="64" src="images/3ds.png"></div>
<div class="consoleDesc">Little Text is fine</div>
<div class="clearfix"></div>
</div>
<div class="col-lg-4 consoleRed">
<div class="consoleIcon"><img width="64" height="64" src="images/3ds.png"></div>
<div class="consoleDesc">When i add too much text it ends up pushing the whole div onto the new line When i add too much text it ends up pushing the whole div onto the new line When i add too much text it ends up pushing the whole div onto the new line When i add too much text it ends up pushing the whole div onto the new line</div>
<div class="clearfix"></div>
</div>
<div class="col-lg-4 consoleRed">
<div class="consoleIcon"><img width="64" height="64" src="images/3ds.png"></div>
<div class="consoleDesc">Not sure why</div>
<div class="clearfix"></div>
</div>
</div>
答案 3 :(得分: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>
在较新版本的nodejs中,您可以像上面的示例一样使用async await
请注意,$ .ajax不是节点功能。它仅用于演示
您可以对任何返回promise的函数使用await。 对于下一个示例,您需要安装请求包并使用Node&gt; = 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();