Является ли эта комбинация одного синхронного и одного асинхронного процесса запущенным одновременно? - PullRequest
1 голос
/ 22 февраля 2020

Скажите, пожалуйста, означают ли результаты, перечисленные в конце этого фрагмента, что обещания p5() и f5() обрабатываются одновременно?

В моем коде проекта sync() создает и возвращает фрагмент документа для замены узла в DOM, но не заменяет его, а p5() является операцией чтения-записи базы данных indexedDB. Я не хочу заменять существующий узел новым фрагментом, пока операция с базой данных не будет выполнена успешно, и я хочу предоставить пользовательские параметры, основанные на том, почему p5() или f5() могли завершиться неудачей.

I Интересно, если поместить в обещание синхронную функцию sync(), чтобы она могла быть помещена в Promise.allSettled, это позволило бы этим двум процессам выполняться одновременно и затем проверять ошибки, когда оба урегулированы, вместо ожидания p5() для завершить перед началом построения фрагмента в sync().

Я очень мало знаю о параллелизме, но эти результаты указывают на то, что sync() или f5() потребовалось две секунды, чтобы завершить и завершить за три секунды до p5() и все было улажено за пять секунд вместо того, чтобы занимать всего семь секунд.

Спасибо.

function p5() { 
    return new Promise( (resolve, reject) => {
    setTimeout( () => resolve( 'p5 resolved at : ' + new Date()), 5000 ); }); }
    
function f5() {
  return new Promise( (resolve, reject) => {
    try { resolve( sync() ); }
    catch(e) { reject( e ) }
    }); }
    
function sync() {
  let i, str ='';
  for( i=0; i < 50000000; i++ ) str = str + 'A string of text';
  i = str = null;
  return 'sync complete at : ' + new Date();
 }
 
 console.log( 'start : ' + new Date() );
 Promise.allSettled( [ p5(), f5() ] ).then( (r) => { console.log(r[0]); console.log(r[1]); } );
 
 /* Results:
start : Sat Feb 22 2020 00:36:53 GMT-0500 (Eastern Standard Time)

r[0]:
{ "status": "fulfilled",
  "value": "p5 resolved at : Sat Feb 22 2020 00:36:58 GMT-0500 (Eastern Standard Time)" }

r[1]: 
{ "status": "fulfilled",
  "value": "sync complete at : Sat Feb 22 2020 00:36:55 GMT-0500 (Eastern Standard Time)" }
*/

    function p5() { 
        return new Promise( (resolve, reject) => {
        setTimeout( () => resolve( 'p5 resolved at : ' + new Date()), 5000 ); }); }
        
    function f5() {
      return new Promise( (resolve, reject) => {
        try { resolve( sync() ); }
        catch(e) { reject( e ) }
        }); }
        
    function sync() {
      let i, str ='';
      for( i=0; i < 50000000; i++ ) str = str + 'A string of text';
      i = str = null;
      return 'sync complete at : ' + new Date();
     }
     
     console.log( 'start : ' + new Date() );
     Promise.allSettled( [ f5(), p5() ] ).then( (r) => { console.log(r[0]); console.log(r[1]) });
     
/*     
start : Sat Feb 22 2020 01:37:08 GMT-0500 (Eastern Standard Time)

{"status": "fulfilled",
  "value": "sync complete at : Sat Feb 22 2020 01:37:10 GMT-0500 (Eastern Standard Time)"}

{"status": "fulfilled",
  "value": "p5 resolved at : Sat Feb 22 2020 01:37:15 GMT-0500 (Eastern Standard Time)" }
*/

1 Ответ

2 голосов
/ 22 февраля 2020

Поскольку вы сначала вызвали фактическую асинхронную операцию p5(), она запустится и будет работать в фоновом режиме, пока выполняется синхронная операция f5().

Асинхронный p5() не может обработать свое завершение до тех пор, пока не будет выполнен синхронный код, потому что основной поток JS может одновременно выполнять только одну операцию, а синхронный код блокирует событие l oop поэтому никакие события завершения из каких-либо асинхронных операций не могут быть обработаны до тех пор, пока не будет выполнена синхронная f5().

Если вы переключили код для переупорядочения p5() и f5(), например:

 Promise.allSettled( [ f5(), p5() ] ).then(...)

Тогда параллелизма не будет, потому что p5() даже не запустится, пока не будет завершено f5().

Интересно, если в обещание поместить синхронную функцию sync(), так то, что он может быть помещен в Promise.allSettled, позволит этим двум процессам выполняться одновременно и затем проверять ошибки, когда оба достигнута, вместо ожидания завершения p5 () перед началом построения фрагмента в sync().


К вашему сведению, нет никакого реального преимущества в переводе вызова на sync() в обещании. Вы могли бы также просто сделать это:

p5().then(...);
f5();

Это даст вам одинаковое общее время выполнения, пока оба не будут выполнены, потому что p5() все еще запускается первым и запускается в фоновом режиме и снова не может обрабатывать событие завершения до тех пор, пока не будет выполнена блокировка f5().


Кроме того, вы должны знать, что вам не нужно заключать sync() в обещание. Вы также можете передавать простые значения в Promise.all() или Promise.allSettled(). Итак, вы также можете сделать это:

Promise.allSettled([p5(), sync()]).then(...)

И это будет работать так же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...