Необработанный отказ от обещания асинхронного ожидания цепи - PullRequest
0 голосов
/ 17 сентября 2018

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

У меня есть

  async foo(req, res, next) {
    try {
      await scan(req.params.stack);
      res.send('ok');
    } catch (err) {
      res.status(500).send('fail');
    }
  }

async scan(stack) {
  try {
    const libs = [1,2,3];
    const promises = libs.map(async l => analyze(stack, l)
      .catch((err) => { throw new Error(err); }));
    return q.allSettled(promises)
      .then((results) => {
        const rejected = results.filter(r => r.state === 'rejected');
        if (rejected.length === results.length) throw new Error('Failed');
        return results;
      })
      .catch((err) => {
        throw new Error(err);
      });
  } catch (err) {
    throw new Error(err);
  }
}

async function analyze(stack, libraries) {
  try {
    const config = await buildConfiguration(stack, libraries);
    return await databaseInsertion(vulnsObject);
  } catch (err) {
    return Promise.reject('Error while trying to analyze libs');
  }
}

Каким-то образом я получаю этот дикийпредупреждение, и я не знаю, где я не улавливаю ошибку.

Конечно, я делаю сбой конфигурации сборки, чтобы проверить ошибку, но вместо того, чтобы нормальный поток исправлял ошибку, я получил это:

(node:415) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: Error while trying to analyze libs

Использую ли я асинхронное ожидание?Есть ли какой-нибудь шаблон, которому я должен следовать, чтобы связать асинхронное ожидание?

Дикая вещь в том, что функция foo работает хорошо, то есть res.status. (500) .send ('fail');работает, и я получаю ответ

Когда я использовал обычные обещания, эта ошибка не появлялась.

Я действительно застрял здесь

Ответы [ 3 ]

0 голосов
/ 17 сентября 2018

При использовании функции сканирования async-await вы смешивали .then() .catch() водопад с await.async-await обрабатывает обещания так же хорошо, как .then().Поэтому придерживайтесь одного потока и попробуйте смешать оба в одной функции или в другой.

async foo(req, res, next) {
    try {
        await scan(req.params.stack);
        res.send('ok');
    } catch (err) {
        res.status(500).send('fail');
    }
}

async scan(stack) {
  try {
    const libs = [1,2,3];

    // This libs.map functions return promise. then why not use await?
    const promises = await libs.map(async l => analyze(stack, l);

    // Again q.allSettled returns promise, use await here too
    let results = await q.allSettled(promises);

    const rejected = results.filter(r => r.state === 'rejected');

    if (rejected.length === results.length) throw new Error('Failed');

    return results;

  }

  // If any promise call reject function will be in catch
  catch (err) {
    throw new Error(err);
  }
}

async function analyze(stack, libraries) {
    try {
        const config = await buildConfiguration(stack, libraries);
        return await databaseInsertion(vulnsObject);
    }
    catch (err) {
        console.log(err);
        return null;
    }
}
0 голосов
/ 26 сентября 2018

В анализе () вы возвращаете Project.reject (), но анализ () является асинхронной функцией.Поэтому он разрешает любое возвращаемое вами значение и отклоняет любую выдаваемую ошибку.

    async function analyze(stack, libraries) {
        try {
            const config = await buildConfiguration(stack, libraries);
            return await databaseInsertion(vulnsObject);
        } catch (err) {
            return Promise.reject('Error while trying to analyze libs');
        }
    }

Поэтому, когда функция анализа обнаруживает ошибку, вы создаете отклонение, а затем разрешаете функцию.Так что Promise.reject('Error while trying to analyze libs'); не обрабатывается.Поскольку асинхронные функции всегда возвращают обещание, которое разрешается при любом возврате и отклоняет все, что вы бросаете, ваша функция анализа всегда будет разрешаться.Попробуйте сделать это ...

    async function analyze(stack, libraries) {
        try {
            const config = await buildConfiguration(stack, libraries);
            return await databaseInsertion(vulnsObject);
        } catch (err) {
            throw Error('Error while trying to analyze libs');
        }
    }

Еще одна вещь, которую я вижу как возможную проблему в этом коде, - даже если вы передаете map(async func) асинхронную функцию, это не волнует.Он не будет ждать завершения каждой функции перед вызовом следующей.

const promises = libs.map(async l => analyze(stack, l)
      .catch((err) => { throw new Error(err); }));
    return q.allSettled(promises)
      .then((results) => {
        const rejected = results.filter(r => r.state === 'rejected');
        if (rejected.length === results.length) throw new Error('Failed');
        return results;
      })
      .catch((err) => {
        throw new Error(err);
      });

Ниже приведены два изменения

const promises = libs.map(async l => await analyze(stack, l)
      .catch((err) => { throw new Error(err); }));
    return q.allSettled( await promises)
      .then((results) => {
        const rejected = results.filter(r => r.state === 'rejected');
        if (rejected.length === results.length) throw new Error('Failed');
        return results;
      })
      .catch((err) => {
        throw new Error(err);
      });

Я добавил ожидание перед функцией анализа и ожидание передпередача переменной обещания в q.allSettled().

0 голосов
/ 17 сентября 2018

Вызов функции async (здесь analyze) вернет обещание, которое будет разрешено или отклонено в соответствии с возвращаемым значением функции async или сгенерированной ошибкой.

Теперь функция analyze обрабатывает выданную ошибку, но при возникновении ошибки она возвращает Promise.reject().Promise.reject() - это необработанное отклонение здесь, о чем говорит журнал.

В терминах синхронной функции эквивалент будет

function sync() {
  try {
    // do something dangerous
  } catch (ex) {
    throw Error('Something bad happened'); // this error is still being thrown and nobody is handling it
  }
}

Для обработки этой ошибки вы можете сделатьследующее, когда вы вызываете sync, оберните его в try и перехватите снова

try {
  sync();
} catch (ex) {
  console.error(ex); // not gonna throw another exception, otherwise the program might crash
}

Теперь, эквивалент этого переноса для функции analyze будет использовать другую асинхронную функцию, или лучше, так как вызов async функция вернет Promise, используйте метод catch для Promise

analyze()
  .then(() => console.log('My work is done here'))
  .catch(ex => console.error(ex)); // NOTE: not throwing another exception

Еще лучше было бы не возвращать отклонение от catch во-первых, таким образом, делая analyze,

async function analyze(stack, libraries) {
  try {
    const config = await buildConfiguration(stack, libraries);
    return await databaseInsertion(vulnsObject);
  } catch (err) {
    console.error(err); // not eating up good errors with something vague is always good
    return null; // or something else to signify that insert failed
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...