2017-01-16 53 views
0

我必須根據給定的配置文件在循環中創建承諾,並在全部解決時返回響應。代碼如下:在循環中創建承諾

{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調用。

回答

0

你定義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}); 
     }); 
    }); 
};