Могу ли я запустить и забыть обещание в nodejs (ES7)?

Я хотел бы запустить этот код с помощью babel:

redisClientAsync.delAsync('key');
return await someOtherAsyncFunction();

внутри асинхронной функции без ожидания первой строки. это нормально?

как еще я могу запустить то, что мне все равно?

Могу ли я просто запустить невыполненную функцию del ('key', null) без обратного вызова?


person arisalexis    schedule 03.09.2015    source источник
comment
Это нормально, если процесс, который его запускает, не завершается до завершения асинхронного вызова.   -  person mostruash    schedule 03.09.2015
comment
Вы используете Babel? Это особенность ES7.   -  person MinusFour    schedule 03.09.2015
comment
@MinusFour Да, я использую babel   -  person arisalexis    schedule 03.09.2015
comment
@mostruash это невозможно знать, да? Я просто создам состояние гонки   -  person arisalexis    schedule 03.09.2015


Ответы (3)


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

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

Это нормально? Как я могу запустить то, что мне все равно?

Наверное, это не нормально. Если вам действительно все равно, вы не запускали его с самого начала. Таким образом, вы должны четко и ясно указать, что вас волнует (а что нет):

  • ты хочешь подождать? (для побочных эффектов)
  • тебе нужен результат?
  • вы хотите ловить исключения?

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

void (await someAsyncFunction()); // or omit the void keyword,
                                  // doesn't make a difference in an expression statement

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

… someAsyncFunction().catch(function ignore() {}) …

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

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

var [_, res] = await Promise.all([
    someAsyncFunction(), // result is ignored, exceptions aren't
    someOtherAsyncFunction()
]);
return res;
person Bergi    schedule 03.09.2015
comment
спасибо, что было исчерпывающим. Если мне не нужен результат, то ошибка, и я не хочу ждать, что лучше всего внутри асинхронной функции. выполнить обещание или запустить обычную функцию (не обещанную) с нулевым обратным вызовом (или функцией, которая ничего не делает)? - person arisalexis; 04.09.2015
comment
В этом случае вы, вероятно, также можете пропустить обещание. Я бы все равно передал обратный вызов, который явно ничего не делает, чтобы показать, что он асинхронный, но вы игнорируете ошибки. - person Bergi; 04.09.2015
comment
будет ли вызван следующий .then, если он разрешится? Я бы этого не хотел. - person mylord; 18.04.2017
comment
@ милорд, я не понимаю, что ты имеешь в виду. onfulfill обратные вызовы всегда вызываются, когда обещание выполняется. - person Bergi; 18.04.2017
comment
Есть ли способ в основном использовать обещание, но не продолжать его в .then? Почему? Потому что я не всегда хочу изменять структуру блока / области видимости только для того, чтобы вызвать функцию (обещание), когда мне не нужно делать что-то конкретное после вызова. - person mylord; 09.05.2017
comment
Как я могу опустить обещание, в основном, при вызове функции, которая вызывает / возвращает обещание? То есть, как я могу назвать это так, чтобы он просто ничего не делал после выполнения? Однако я хотел бы, чтобы исключения были хотя бы распечатаны, если не обрабатываются в любом / следующем .catch. - person mylord; 09.05.2017
comment
@mylord Я понятия не имею, что вы имеете в виду под изменением структуры блока / области видимости. А без then вы не сможете использовать обещание. Конечно, вы можете просто вызвать функцию и отбросить (проигнорировать) обещание, которое она возвращает - похоже, это именно то, что вам нужно. Создание обещания нельзя пропустить, но в этом нет необходимости. Вы получите unhandledRejection за исключения. - person Bergi; 09.05.2017
comment
@Bergi, проблема в том, что если вы просто вызовете функцию promisified, в этом случае будет вызвана любая последняя функция next .then () в вашей цепочке обещаний, непреднамеренно. Как вы можете вызвать обещанную функцию и заставить ее забыть выполнить какой-либо .then после того, как она разрешится? - person mylord; 13.05.2017
comment
@mylord Нет, обратный вызов then не будет вызван непреднамеренно, если вы просто не установите его в первую очередь (в том числе из цепочки или await). - person Bergi; 13.05.2017
comment
@Bergi Я должен попробовать это еще раз, но тогда 9 не произойдет, независимо от того, добавим ли мы возврат к строке 7? hastebin.com/faduqiribu.php - person mylord; 14.05.2017
comment
@mylord, если вы вернетесь в строку 7, строка 10 будет выполнена только тогда, когда будет выполнено promisifiedFunction() обещание. Если вы этого не сделаете, он будет выполнен, когда будет выполнена цепочка обещаний (которая сейчас полностью не связана с promisifiedFunction()). Если у вас все еще есть проблема с этим, вам, вероятно, следует задать новый вопрос с полным примером и описанием. - person Bergi; 14.05.2017

внутри асинхронной функции без ожидания первой строки. это нормально?

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

как еще я могу запустить то, что мне все равно?

Однако во многих отношениях простой вызов функции обещания работает. Ваш del без обратного вызова, вероятно, будет работать в этом случае, но некоторые функции не защищают от непрохождения обратных вызовов, поэтому вы можете вместо этого передать пустую функцию (.del('key', () => {})).

Однако вы хотите убедиться, что знаете об этом, даже если вы не хотите нарушать работу кода - поэтому, пожалуйста, подумайте о добавлении обработчика событий process.on("unhandledRejection',, чтобы явно игнорировать эти конкретные исключения или подавить их с помощью:

redisClient.delAsync('key').catch(()=>{});

Или, что лучше, что-то вроде:

redisClient.delAsync('key').catch(logErr);
person Benjamin Gruenbaum    schedule 04.09.2015
comment
Я чувствую, что этот ответ отвечает на вопрос намного лучше, чем другой. - person PRMan; 06.11.2019
comment
Отличное объяснение. - person Sunil Patel; 10.02.2020

Судя по всем исследованиям, которые я провел до сих пор, я считаю, что это нормально, если вы гарантируете, что функция, которую вы не await используете для , гарантирует способ обработки собственных ошибок в случае, если бывает. Например, try-catch, охватывающий все тело функции, как вы видите в следующем фрагменте для asyncFunction.

Не имеет значения, выбрасывает ли функция синхронно или асинхронно. Это гарантирует, что ваш mainFunction завершится несмотря ни на что. Это ключевой момент.

Если вы этого не гарантируете, вы рискуете:

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

// THIS IS SOME API CALL YOU DON'T WANT TO WAIT FOR

const mockAPI = () => {
  console.log("From mockAPI");
  return new Promise((resolve,reject) => {
    setTimeout(() => reject("LATE THROW: API ERROR"), 500);
  });
};

// THIS IS THE SOME ASYNC FUNCTION YOU CALL BUT NOT AWAIT FOR

const asyncFunction = async (syncThrow) => {
  try {
    console.log("Async function START");
    if (syncThrow) throw new Error("EARLY THROW");
    await mockAPI();
    console.log("Async function DONE");
  }
  catch(err) {
    console.log("From async function catch");
    console.log(err.message || err);
    return;
  }
};

// THIS IS YOUR MAIN FUNCTION

const mainFunction = async (syncThrow) => {
  try {
    console.clear();
    console.log("Main function START");
    asyncFunction(syncThrow);
    console.log("Main function DONE <<< THAT'S THE IMPORTANT PART");
  }
  catch(err) {
    console.log("THIS WILL NEVER HAPPEN");
    console.log(err);
  }
};
<div>
  <button onClick="mainFunction(true)">Sync throw</button>
  <button onClick="mainFunction(false)">Async throw</button>
</div>

person cbdeveloper    schedule 11.02.2021