Js: Цепочки обещают цепочки в четкой и понятной форме - PullRequest
0 голосов
/ 11 октября 2018

Здравствуйте, переполнения,

В настоящее время я работаю над моим проектом, использующим сервер узлов с хранилищем данных Монго.В настоящее время я пишу некоторые функции для заполнения базы данных.
Примерами объектов в базе данных являются «Пользователи», «Классы», «Школьные годы», «Оценки учащихся» и т. Д.
Все функции для создания таких объектов реализованы следующим образом.:

    function popUser(users){
        chain = [];
        users.forEach((v,i,a)=>{
            let p = new Promise(function(res,rej){
                let newU = new User(v);
                newU.save(()=>{
                    err && rej(err);
                    res();
                });
            });
            chain.push(p);
        });
        return chain
    }

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

С Обещаниями я мог бы сделать что-то вроде этого:

popUser(users).then(popClasses).then(...). ... .catch((err)=>{})

С Цепями Обещаний я знаю, что могу сделать следующее

Promise.all(usersChain).then(()=>{
    //make a new chain for Classes
    Promise.all(classesChain).then (()=>{},(err)=>{})
},(err)=>{})

Я думаю, мы можем согласиться с тем, чтостановится довольно трудно читать и понимать, поэтому возникает вопрос:

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

Редактировать: чтобы быть понятнее, usersChain и cleassesChains - это массивы Promises для создания и вставки некоторых объектов (или объектов) в базу данных.Я не могу сделать одну цепочку, потому что некоторые объекты могут быть вставлены после того, как некоторые другие объекты уже были вставлены.

Редактировать: Подожди, я могу просто позвонить

Promsie.all(populateCountersPromise).then(promise1).then(promise2).catch((err)=>{})

Ответы [ 3 ]

0 голосов
/ 11 октября 2018

Обратные вызовы Mongoose являются устаревшим API.Mongoose поддерживает обещания в течение длительного времени и не нуждается в обещании.

Для одновременных обещаний forEach может быть заменено на map, это точный вариант использования для последнего:

function popUser(users){
  return Promise.all(
    users.map(userData => new User(userData).save())
  );
}

async..await можно использовать в остальных случаях, когда обещания должны быть последовательными:

try {
  await popUser(users);
  await popClasses();
  ...
} catch (err) {
  ...
}
0 голосов
/ 11 октября 2018

Почему бы не вернуть Promise.all(chain) в функции popUser.

Возвращение обещания лучше соответствует семантике popUser, которая является функцией выполнения чего-либо асинхронно. Возврат массива обещания сбивает с толку.

Тогда вы можете использовать popUsers.then(popClasses).then(...). ... .catch((err)=>{}), чтобы поставить в очередь обещания

0 голосов
/ 11 октября 2018

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

Если вы используете такие ярлыки:

err && rej(err);
res();

Вы должны знать, чтоони означают, потому что это равно:

if( err ) { 
  rej(err);
}
res();

Так что, если происходит ошибка, вызываются и rej, и res.

Из вашего popUser вы возвращаете массивОбещания, поэтому popUser(users).then(popClasses) потерпит неудачу, потому что вы не можете вызвать .then для массива.

Первое, что вы должны сделать, это очистить вашу popUser функцию:

function popUser(users) {

  let promises = users.map((v, i, a) => {
    return new Promise(function(res, rej) {
      let newU = new User(v);
      newU.save(err => {
        if (err) {
          rej(err)
        } else {
          res()
        }
      });
    });
  });

  return Promies.all(promises)
}

Используйте .map вместо forEach с push, потому что это с самого начала проясняет, что вы делаете.И используйте Promies.all, чтобы вернуть Promise из вашей функции, который ожидает сохранения всех пользователей. Если вы сделаете то же самое для popClasses, вы можете написать его следующим образом:

popUser(users)
   .then(popClasses)
   .then(...)
   .catch((err)=>{})

Если вы действительно хотитенапишите его, как в последнем фрагменте кода, а затем измените его на:

Promise.all(usersChain)
  .then(() => Promise.all(classesChain))
  .then(() => {})
  .catch(err => {})

Многие API-интерфейсы теперь поддерживают как классические обратные вызовы, так и Promises, так что вы можете улучшить свой popUser:

function popUser(users) {
  let promises = users.map(v => new User(v).save())
  return Promies.all(promises)
}
...