我必须根据给定的配置文件在循环中创建promises,并在所有问题都得到解决后返回响应。代码是这样的-
{for(let type in spotlight){
switch (type){
case "outliers":{
let ops= spotlight[type];
for(let i=0;i<ops.length;i++){
(function(op){
let p= new Promise(function(resolve,reject){
let reqUrl= urlCreator(op.uri,op.query);
//console.log("--------------------"+reqUrl);
apiService.get(reqUrl,function(isSuccess,data){
if(!isSuccess){
return reject(data);
}
// console.log(isSuccess);
// console.log(data);
// console.log("trend is ------"+JSON.stringify(op));
// create objects array
// let temp= [];
// let overallScore= data.overall.score;
// for(let day in overallScore){
// temp.push({"key": day,"value": parseFloat(overallScore[day])});
// }
//let outliers= stats.outliers(temp,"key","value");
resolve({"type":type,"name": op.name,"data": outliers});
})
});
promiseArray.push(p);
}(ops[i]))
}
break;
}
case "filters":{
let ops= spotlight[type];
for(let i=0;i<ops.length;i++){
(function(op){
let p= new Promise(function(resolve,reject){
let reqUrl= urlCreator(op.uri,op.query);
apiService.get(reqUrl,function(isSuccess,data){
if(!isSuccess){
return reject(data);
}
// console.log(isSuccess);
// console.log(data);
// console.log("coc is ------"+JSON.stringify(op));
resolve({"type": type,"name": op.name,"data": data});
})
})
promiseArray.push(p);
}(ops[i]))
}
break;
}
}
}
Promise.all(promiseArray).then(values=>{
return res.json(values);
},
reason=>{
return res.json(reason);
}).catch(reason=>{
return res.json(reason);
})}问题是,承诺永远不会回来,既不会解决,也不会被拒绝。
根据配置文件,它必须命中两个URL,比如u1和u2。我尝试记录输出,以查看哪些请求正在返回。当服务器启动并发出第一个请求时,U1将返回并挂起请求。在刷新时,我收到来自U2的响应,U2和请求挂起,然后在刷新时再次U1,U1,这将继续。在我看来,由于某种原因,只返回一个请求,而另一个请求则位于缓冲区或其他地方,并在发出下一个请求时出现。这两个请求都只发送到本地服务器,我将其路由到外部只是为了利用缓存,因为url被用作缓存的关键字。
我试过使用facebook.com和google.com这样的虚拟url,它工作得很好,一个本地url,另一个像facebook.com也可以,但是当两个url都是本地服务器的时候,它就卡住了。
这是否与节点的单线程性质有关,或者是因为使用相同的套接字来发出两个请求。
PS- I使用npm-request进行URL调用。
发布于 2017-01-17 04:06:09
也许在提出第二个请求之前犹豫不决会解决你的问题。
我做了一些工具,可以帮助你做到这一点。请参阅MacroQTools.js文件,网址为
https://github.com/J-Adrian-Zimmer/JavascriptPromisesClarified.git
发布于 2017-01-17 06:29:29
您将request回调定义为function(success , data),而request使用像function(error , response)一样定义的错误优先回调。
您调用的请求如下:
apiService.get(reqUrl,function(isSuccess,data){
if(!isSuccess){
return reject(data);
}
// console.log(isSuccess);
// console.log(data);
// console.log("coc is ------"+JSON.stringify(op));
resolve({"type": type,"name": op.name,"data": data});
});假装,如果第一个参数丢失,您必须用第二个参数data拒绝它。然而,实际上,它应该是这样的:
apiService.get(reqUrl,function(err,data){
if(err){
reject(err);
}
else{
// console.log(isSuccess);
// console.log(data);
// console.log("coc is ------"+JSON.stringify(op));
resolve({"type": type,"name": op.name,"data": data});
}
});因为request期望错误优先回调(就像节点中接受回调的几乎任何东西一样)。
因此,当请求实际按预期工作时,您的代码必须实际拒绝具有实际实值的承诺,因为当request工作时,isSuccess为空,而data具有实际响应值。
这肯定破坏了一些东西,这是不好的,虽然仅仅修复它可能不能完全解决你的问题:我认为你的请求行为奇怪是因为你的api的一些配置问题,而不仅仅是因为当请求成功时你拒绝了承诺(这将只是send数据作为拒绝的原因)。
另外,您将两次处理Promise.all()的拒绝,将第二个处理程序传递给then并再次调用catch。只需要一个,那就是.catch(handler) is probably better。
我做了一个关于如何使用Promise.all收集异步请求的小工作示例。我使用imdb作为apiService,但任何异步http服务也可以。我没有完全复制你的代码,但我相信你可以调整它来使你的代码工作,至少是使用http服务的那部分代码。
var express = require('express');
var app = express();
var Promise = require('bluebird');
var imdb = require('imdb-api');
app.get('/', controllerHandler );
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});
var apiService = {}
apiService.get = imdb.getReq;
function controllerHandler(request , response){
//like iterating through spotlight.type and returning an array of promises from it.
//in this case the array is from films and Airbag is obviously the best of them
var promises = [{name : 'The Matrix'} , { name : 'Avatar'} , {name : 'Airbag'}].map( createPromise );
//use either .catch(errorHandler) or then( successHandler , errorHandler ). The former is the better:
Promise.all(promises).then( successHandler ).catch( errorHandler );
function successHandler(result){
return response.json(result);
}
function errorHandler(reason){
console.log('There was an error calling to the service:');
console.log(reason);
return response.send('there was an error');
}
}
function createPromise(film){
return new Promise( function(resolve , reject){
apiService.get(film , function(err , data){
if(err)
reject( new Error(err));
else
resolve( {title : data.title , year : data.year} );
});
});
};https://stackoverflow.com/questions/41676698
复制相似问题