2016-12-06 7 views
1

Я использую библиотеку Bluebird с NodeJS (с каркасом) SailsJSКак захватить событие, в котором разрешены все обещания в массиве?

Promise.all() не захватывая событие, когда все обещания в promises массиве будут решены.

Какие изменения должны быть сделаны для решения этой проблемы?

var Promise = require("bluebird"); 
var request = require('request'); 
var http = require('http'); 

function searchMultiple(titles) { 

    var results = []; 

    return new Promise(function(resolveGlobal, rejectGlobal){ 

    var url = "http://xxx.xxx"; 
    var promises = []; 

    titles.forEach(function (title, index) { 

     promises[index] = new Promise(function (resolve, reject) { 

     var data = {"x":title}; 

     request({ 
      uri: url, 
      method: "POST", 
      body : data 
     }, function(error, response, body) { 
      return resolve(body) 
      } 
      } 
     }, 
     function (error, response, body) { 
      console.log("error"); 
      return resolve(); 
     } 
     ); 
     }) 
    }) 

    Promise.all(promises).then(function(combinedResults) { 
     console.log("successfully resolved all promises"); 
     return resolveGlobal(combinedResults); 
    }).catch(function (reason) { 
     console.log("error"); 
     return rejectGlobal(); 
    }); 

    }) 
} 
+1

Что вы подразумеваете под «не захватом события»? –

+0

@PankajParkar Я хочу решить внешнее обещание ('resolveGlobal()'), когда все обещания в массиве 'promises' решены. –

+0

Избегайте антипаттера конструктора '' Promise' (http://stackoverflow.com/q/23803743/1048572)! – Bergi

ответ

0

Попробуйте это:

var Promise = require('bluebird'); 
var request = require('request'); 

function searchMultiple(titles) { 
    return new Promise(function (resolveGlobal, rejectGlobal) { 
    var url = 'http://xxx.xxx'; 
    var promises = []; 

    titles.forEach(function (title) { 
     promises 
     .push(new Promise(function (resolve, reject) { 
      var data = { 
      'x': title 
      }; 

      request({ 
       uri: url, 
       method: 'POST', 
       body: data 
      }, 
      function (error, response, body) { 
       if (!error && response.statusCode == 200) { 
       return resolve(body); 
       } 

       return reject(error); 
      }); 
     })); 
    }); 

    Promise 
     .all(promises) 
     .then(function (combinedResults) { 
     console.log('successfully resolved all promises'); 

     return resolveGlobal(combinedResults); 
     }) 
     .catch(function (error) { 
     console.log('error'); 

     return rejectGlobal(error); 
     }); 
    }); 
} 

И вызвать функцию:

searchMultiple([...]) 
    .then(function (results) { 
    console.log(results); 
    }) 
    .catch(function (error) { 
    console.log(error); 
    }); 
+0

Что вы изменили? И почему? Пожалуйста, добавьте объяснение в свой ответ. – Bergi

1

Там нет необходимости для вас return resolve(value), как это следует только resolve с заданным значением результата.

Существует также никаких оснований для создания нового обещания в вашей функции searchMultiple, поскольку Promise.all возвращает обещание. Вы должны просто вернуть обещание, которое у вас уже есть!

resolveGlobal() поэтому не нужен, и вместо этого вы можете получить return, так как then обернет его как разрешенное значение.

Все код можно переписать в виде двух очень простых функций

function searchMultiple(titles) { 
    //Empty array of promises 
    var promises = []; 

    var url = "http://xxx.xxx"; 

    //Get a promise for each title and push to array 
    titles.forEach(function(title){ 
    promises.push(getData(title, url)); 
    }); 

    //Wait for all promises to resolve, and return the result 
    return Promise.all(promises) 
    .then(function(arrayOfResults){ 
     //If this only shall return the array, this can be omitted aswell as the catch! 
     return arrayOfresults; 
    }) 
    .catch(function(reason){ 
     //Handle errors 
    }); 
} 

function getData(title, url){ 
    return new Promise(function(resolve, reject){ 
    var data = {"x":title}; 
     request({ 
      uri: url, 
      method: "POST", 
      body : data 
     }, function(error, response, body) { 
      resolve(body) 
      } 
      } 
     }, 
     function (error, response, body) { 
      console.log("error"); 
      //Consider rejecting here instead since you'll get a result that is 'undefined' 
      resolve(); 
     }); 
    }); 
} 

Вы должны рассмотреть отвергая обещание в обработчик ошибок вместо разрешения его с неопределенным значением. Вы можете столкнуться с ошибками в будущем, если вы получите массив результатов, имеющий значения undefined.

+0

Вы забыли 'url' и' title' в качестве параметров функции 'getData' – Bergi

+1

Обратите внимание, что' .then (function (arrayOfResults) {return arrayOfresults;}) 'бессмысленно и должно быть опущено, если с массивом ничего не сделано. – Bergi

+1

Спасибо, пропустил это! Верно о '.then (..)' на 'Promise.all (..)', я пропустил распечатку в консоли, но, возможно, должен был включить это, чтобы было более понятно, почему сохранить '.then (..) '. –