2017-01-16 7 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); 
})} 

Проблема в том, что обещания никогда не возвращаются, не разрешаются и не отклоняются.
Согласно конфигурационному файлу, он должен ударить по двум URL-адресам, например, u1 и u2. Я попытался зарегистрировать вывод, чтобы увидеть, какие запросы возвращаются. Когда сервер запущен и выполняется первый запрос, U1 возвращается и req зависает. при обновлении я получаю ответ от U2, U2 и зависает запросы, затем снова обновляется U1, U1, и это продолжается. Мне кажется, что по какой-то причине возвращается только один запрос, а другой сидит в буфере или что-то еще и приходит, когда делается следующий запрос. Оба запроса поступают только на локальный сервер, я маршрутизирую его извне, только чтобы использовать кеш, поскольку URL-адрес используется в качестве ключа для кеша.
Я попытался использовать фиктивные URL-адреса, такие как facebook.com и google.com, и он отлично работает. Использование одного локального URL-адреса и другого, например facebook.com, также работает, но когда оба URL-адреса имеют локальный сервер, он застревает.
Имеет ли это какое-либо отношение к однопоточной природе узла или из-за использования одного и того же сокета для выполнения обоих запросов.
PS- Я использую npm-запрос для вызова URL-адресов.

ответ

0

Возможно, нерешительность перед тем, как сделать второй запрос, решит вашу проблему.

Я сделал несколько инструментов, которые могли бы помочь в этом. Смотрите файл MacroQTools.js в

https://github.com/J-Adrian-Zimmer/JavascriptPromisesClarified.git

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 является недействительным и data имеет реальное значение отклика.

Это, безусловно, что-то ломает и не очень хорошо, хотя его исправление, возможно, не решит вашу проблему полностью: Я считаю, что ваши запросы действуют странно, потому что некоторые проблемы с конфигурацией вашего api не только потому, что вы отклоняя обещания, когда запросы успешны (это будет только send данные как причина отклонения).

Также вы обрабатываете отказ от Promise.all() дважды, передавая второй обработчик then и снова вызывающий catch. Требуется только один, и .catch(handler)is probably better.

Я сделал небольшой рабочий пример о том, как вы можете использовать Promise.all для сбора асинхронных запросов.Я использовал imdb как apiService, но любая служба async 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}); 
     }); 
    }); 
};