在循环中创建承诺
我必须根据给定的配置文件在循环中创建承诺,并在全部解决时返回响应。代码如下:在循环中创建承诺
{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);
})}
问题是承诺永远不会返回,既不解决也不会被拒绝。
根据配置文件,它必须命中两个网址,说u1和u2。我试图记录输出以查看哪些请求正在返回。当服务器启动并且第一次请求时,U1返回并且请求挂起。在刷新时,我从U2,U2和请求挂起得到响应,然后再次刷新U1,U1,并继续。在我看来,出于某种原因,只有一个请求被返回,而其他的请求被放入缓冲区或其他地方,并在下一个请求发生时进入。这两个请求都只对本地服务器进行,我只是为了利用缓存而将其路由到外部,因为url正被用作缓存的关键字。
我试着使用像facebook.com和google.com这样的虚拟网址,它的工作原理非常好。使用一个本地URL和另一个像facebook.com也可以,但是当这两个网址都是本地服务器时,它会卡住。
它是否与节点的单线程性质有关,或者是因为使用相同的套接字来发出这两个请求。
PS-我正在使用npm-request进行URL调用。
在提出第二次请求之前可能会犹豫,这可以解决您的问题。
我做了一些工具,可以帮助。见MacroQTools.js文件在
https://github.com/J-Adrian-Zimmer/JavascriptPromisesClarified.git
你定义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});
});
假装,如果第一个参数未命中,你有第二个参数来拒绝它,数据。虽然,真的,这将是这样的:
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
为null,并且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});
});
});
};