Как использовать функцию единого перехвата для вложенного асинхронного ожидания? - PullRequest
0 голосов
/ 21 мая 2019

У меня есть этот код:

on('connection', async(socket) => {
  try {
    const promises = members.map(async(member) => {
      try {
        const users = await User.find({})
        const _promises = users.map(async() => {
          try {
            //some code here
          } catch (err) {
            console.log(err)
          }
        })
        await Promise.all(_promises)
      } catch (err) {
        console.log(err)
      }
    })
    await Promise.all(promises)
  } catch (err) {
    console.log(err)
    throw err
  }
})

Как вы видите, у меня есть try catch для каждой вложенной функции async.Можно ли настроить код для использования только одного catch или как-то упростить его?

Ответы [ 2 ]

2 голосов
/ 21 мая 2019

Вы можете иметь только один await на верхнем уровне обработчика. Если Обещания, порожденные внутри всей цепочки, объединяются в Обещание, которое await редактируется на верхнем уровне (как в вашем примере), эта вершина await будет отлавливать ошибки, возникающие в любом месте внутри.

Но ваша секция catch должна не throw еще одна ошибка, если .on также не обработает отклонения Promise, в противном случае вы получите необработанное отклонение Promise:

on('connection', async(socket) => {
  try {
    const promises = members.map(async(member) => {
      const users = await User.find({})
      const _promises = users.map(async() => {
        //some code here which may throw
      });
      await Promise.all(_promises);
    });
    await Promise.all(promises);
  } catch (err) {
    console.log(err);
  }
})
  • Если await User.find throws, то массив promises будет содержать Promise, который отклоняет, что означает, что верхний await Promise.all(promises); бросит и будет пойман
  • Если что-то внутри users.map бросит, _promises будет содержать Обещание, которое отклоняет, поэтому await Promise.all(_promises); бросит. Но это внутри обратного вызова const promises = members.map, так что в результате promises также будет содержать отклоненное обещание - так что оно будет также перехвачено await Promise.all(promises);.
0 голосов
/ 21 мая 2019

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

try {

   throw "an error";

}
catch(e) {
   console.log(e);   //output: "an error"
}

Теперь рассмотрим это

try {

  try {

   throw "an error";

  }
  catch(e) {

    console.log(e);   //output: "an error"

  }

}
catch(e) {
   console.log(e);   //This line is not going to be executed
}

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

Посмотрите на следующий код:

try {

  try {

   throw {internalError: 101};

  }
  catch(e) {

    //Attach more info and throw again 
    e.additionalInfo = 'Disconnected when gathering information';
    throw e;

  }

}
catch(e) {
   e.message = 'Cannot get information'
   console.log(e);   //Final error with lot of information
}
...