2017-08-27 53 views
1

通过举个最简单的例子,假设他们是2个或更多需要通过发出HTTP请求提交数据的帅哥,其中一个帅哥提交的数据必须等待其他帅哥发送的数据发送给服务器才能被解析。下面是我试图在Node.js的完成图像:如何同步2个或更多异步请求的数据并发送解析​​数据的响应?

enter image description here

当数据解析需要将其送回为每一个帅哥的响应。问题是我坚持实现这个任务(我使用http模块,长轮询,后来我会使用websocket),问题驻留在回调本质,我尝试使用脏方法,如制作一个数组是直到所有人都提交并在setInterval函数的帮助下进行检查,无论何时需要解析数据等等。

是否有任何更清洁,更杂乱的方式来执行这些任务?

+0

我会说,从两个客户期待准同时要求*是*一个烂摊子。 – Bergi

回答

2

我想给一个唯一的ID (这两个客户端都知道),然后将相关数据存储在数据库中或直接存储在服务器RAM中。有待处理的请求(请求 - 等待)对服务器不利,因为它必须保持越来越多的开放连接,并且对客户端不利,因为他看到一个旋转的圆圈而不知道发生了什么。我宁愿做到以下几点:

1. client sends request with data 
     2. data gets stored, a *please wait* is returned 
3. the page reloads all two seconds 
     4. if all the datas there, return the data 
     5. if not, return *please wait* and goto 3 

一个pseudoimplementation应该是这样的:

var processes = new Map(); 

function Process(){ 
    do { 
    var id = Math floor(Math.random()*10**10); 
    }while(processes.has(id)); 
    this.id = id; 
    processes.set(id,this); 
} 

Process.prototype.pending = function(res){ 
if(this.first && this.second) 
    return res.end(this.first + this.second); 

res.end(` 
    <html> 
    <body> 
    Please wait... 
    <script> setTimeout(location.reload.bind(location),2000); 
    </script> 
    </body> 
</html>`); 
}; 

//the routing 
var app = Express(); 

app.get("/create",function(req,res){ 
var p = new Process(); 
req.end(p.id); 
}); 

app.get("/first/:id/:data",function(req,res){ 
var p = processes.get(req.params.id); 
if(!p) return res.end("id not found"); 
p.first = req.params.data; 
p.pending(res); 
}); 

app.get("/second/:id/:data",function(req,res){ 
var p = processes.get(req.params.id); 
if(!p) return res.end("id not found"); 
p.second = req.params.data; 
p.pending(res); 
}); 
+0

所以它就像客户端连续请求完成的数据,以防服务器应答a.k.a搜索其他请求正在进行,直到最终它接收到完成的数据,下一个请求与数据完成?对于服务器来说,接收这么多的请求(或者websocket将变得不那么容易处理饥饿的任务),这不是一项单调乏味的任务吗? – DomainFlag

+1

@domainFlag,是的上面的代码是没有websockets,我相信一个2秒轮询不那么沉重,然后一个未决的请求。 Websockets的工作原理类似(它们并不总是处于等待状态,而是使用轮询),但是它们比常规请求更轻,因此使用websockets可能会提高性能。然而,我还没有与他们一段时间,这就是为什么我没有添加一个例子... –

+0

你的解决方案效果更好,然后其他人提供的一切,这是更好的然后我尝试了一切,非常感谢你 – DomainFlag

1

目前最简单的方法是,如果你使用的回调,而不是最简单的方法是使用async模块使用Promise.all

function firstAsyncRequest() { 
    return new Promise((resolve, reject) => { 
    // do your async call and then resolve(); 
    // or reject() if any error; 
    }); 
} 


function secondAsyncRequest() { 
    return new Promise((resolve, reject) => { 
    // do your async call and then resolve(); 
    // or reject() if any error; 
    }); 
} 

Promise.all([firstAsyncRequest, secondAsyncRequest]) 
    .then(arrayOfResults => { 
     //do your logic 
    }) 
    .catch(err => { 
     //catch your error 
    }) 

然后async.parallel

async.parallel([ 
    function(callback) { 
     setTimeout(function() { 
      callback(null, 'one'); 
     }, 200); 
    }, 
    function(callback) { 
     setTimeout(function() { 
      callback(null, 'two'); 
     }, 100); 
    } 
], 
// optional callback 
function(err, results) { 
    // the results array will equal ['one','two'] even though 
    // the second function had a shorter timeout. 
}); 
+0

我可以如上所述以异步方式将Promise.all用于多个进程吗? – DomainFlag

+2

您可以使用'Promise.all()'作为任意多个异步请求,只要它们“全部”解决,您将在'.then()'阶段的数组中接收它们的值。但是,如果其中一个请求抛出错误,则整个事件将停止,您只会'catch()'一个错误。 – Redu

+0

不知道,但承诺和异步解决方案不起作用,因为当你不知道什么时候客户端请求会被服务器拦截并且它是一堆范围,或者我错了时,你不能提供其他回调? – DomainFlag

0

正如我在我的评论都提到promise.all()是好的,但你没有上一次承诺解决任何控制其中一人被拒绝。

相反,您可以用.reduce()对您的承诺进行排序,并且您将对解决和拒绝的承诺拥有更多的控制权。

var pr1 = new Promise((v,x) => setTimeout(_ => Math.random() > 0.2 ? v("promise 1 resolved value") : x("Promise 1 rejected"),150)), 
 
    pr2 = new Promise((v,x) => setTimeout(_ => Math.random() > 0.2 ? v("promise 2 resolved value") : x("Promise 2 rejected"),120)), 
 
    pr3 = new Promise((v,x) => setTimeout(_ => Math.random() > 0.2 ? v("promise 3 resolved value") : x("Promise 3 rejected"),60)), 
 
    pr4 = new Promise((v,x) => setTimeout(_ => Math.random() > 0.2 ? v("promise 4 resolved value") : x("Promise 4 rejected"),220)), 
 
    pr5 = new Promise((v,x) => setTimeout(_ => Math.random() > 0.2 ? v("promise 5 resolved value") : x("Promise 5 rejected"),180)); 
 

 
[pr1,pr2,pr3,pr4,pr5].reduce((p,c) => p.then(v => (console.log(`doing something with ${v} and will proceed with the next`),c), 
 
              x => (console.log(`Error ${x} however i will proceed with the next`),c))) 
 
        .then(v => console.log(`finally doing something with ${v}`), 
 
          x => console.log(`Error ${x} received`));