2016-10-14 6 views
1

Привет, я новичок в Promises и зациклен на том, как дождаться всех обещаний в цикле for, чтобы решить, прежде чем переходить к следующему тогда (). Я видел пару обещаний. Все примеры, но мне было непонятно, как их адаптировать для моего следующего кода. В настоящее время он переходит к следующему then() после цикла for и разрешается до завершения цикла for. Любая помощь приветствуется!Обещает внутри для циклов/prom.all, используя psql (pg-prom) в узле

Я использую pg-promise (psql с обещаниями).

Оригинальный код:

function getTeamMembers(aTeam) { 
    let promise = new Promise(function(resolve, reject) { 
     db.getTeamMembers(aTeam.tid) //return sql results rows 
     .then(function(rows){ 
      for(let i=0; i<rows.length; ++i) { //loop through each result row 
      getUserByUsername(rows[i].username) 
       .then(function(cfUser) { //add user from row to aTeam object      
       aTeam.addMember(cfUser); 
       }) 
       .catch(function(e) { 
       reject(e); 
       }); 
      } 
     }) 
     .then(function(){ 
      console.log(aTeam); //confirm added properly 
      resolve(aTeam); //resolve object 
     }) 
     .catch(function(e) { 
      console.log('addMemberToTeamByUsername: '+e.stack); 
      reject(e); 
     }); 
    }); 
    return promise; 
    } 

ответ

2

Я являюсь автором pg-promise.

Ниже приведено несколько соображений о недопустимом использовании Promise.all в этом контексте в ответе, который теперь удален.


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

В случае pg-promise ваших физического контекста состоит из двух вещей:

  • строки запроса будет конвейер через Node.js IO
  • контекста соединения предоставленного пулом соединений

Каждый запрос запроса получает и освобождает соединение из пула соединений, который является очень ограниченным физическим ресурсом. Размер вашего пула по умолчанию равен 10, как установлено базовым драйвером node-postgres. И хотя вы можете увеличить его до 100, это приведет к созданию перегрузки в управлении соединениями, поэтому он не масштабируется. Типичное увеличение должно быть установлено на 20, что примерно равно среднему значению.

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

Такое решение не может масштабироваться вообще, и оно указано как анти-шаблон для выполнения запроса здесь: Tasks versus root/direct queries.

В принципе, то, что он объясняет там необходимо выполнить несколько запросов через задачи:

  • Метод task, если вы не изменяете данные
  • Метод tx (транзакций), если вы меняете данные

Таким образом, вы можете передавать все ваши запросы через одно соединение, что необходимо для обеспечения масштабируемости вашего сервиса.


Там множество примеров в Learn By Example учебник как для Tasks и Transactions.


А учитывая, что вы пытаетесь получить Mutiple родительские строки, а затем несколько дочерних строк, вы должны смотреть на этот вопрос: get JOIN table as array of results with PostgreSQL/NodeJS.

Я также предлагаю прочитать статью Performance Boost, чтобы лучше понять физические ограничения выполнения нескольких запросов и способы их решения.

Пример

function getTeamMembers(aTeam) { 
    return db.task(t=> { 
     return t.map('SELECT * FROM team_members WHERE id=$1', aTeam.id, tm=> { 
      return t.any('SELECT * FROM users WHERE name=$1', tm.username) 
       .then(users=> { 
        tm.users = users; 
        return tm; 
       }); 
     }).then(t.batch); 
    }); 
} 

// usage example: 

getTeamMembers({id: 123}) 
    .then(members=> { 
     // members = array of member objects 
    }) 
    .catch(error=> { 
     // error 
    }); 

Это не единственный способ сделать это, но это самый короткий;)

Этот подход дается лучше рассмотреть в следующий вопрос: get JOIN table as array of results with PostgreSQL/NodeJS.

+0

Интересно, кто это сделал. Но, может быть, вы должны добавить код? – Bergi

+0

@ Bergi, да, я отвечал в спешке, с работы, подробно расскажу, когда получится шанс. Был также наткнулся на критику со стороны автора первого ответа (теперь он удален). Думаю, это просто плохой день. –

+0

Hi Vitaly - вы могли бы предоставить некоторый код в качестве примера? Я бы хотел это увидеть! Я рассмотрю ваши предложения, спасибо за помощь в повышении моих знаний и кода! –