5

Oboe.jsを使用して、非常に大きな JSON ファイルを解析しています

const promises = [];
oboe('http://domain/my-file.js')
  .node('items.*', item => {
    // parseItem() returns a rejected Promise because of invalid JSON items
    promises.push(parseItem(item));
  })
  .done(() => {
    Promise.all(promises).then(() => {
      doSomething();
    });
  })

しかし、私のブラウザコンソールはUncaught (in promise). setTimeout()likeに promise を書いた場合も同様です。

const promises = [];
setTimeout(() => {
  promises.push(Promise.reject());
}, 500);
// some time in the future
Promise.all(promises);

本当に奇妙なのは、最新のブラウザーの動作が異なることです。Firefox Developer Edition ではすべてがエラー メッセージなしで機能し、Chrome では大量のUncaught (in promise). Promise.reject();Chrome では、キャッチなしで書くとすぐにメッセージが表示されます。Firefox と Safari では何も起こりません。

それで、これに対する解決策は何ですか?メッセージを無視しますか?つまり、この動作が実際に公式の promise 仕様にある場合、非同期コードの promise は私にとって本当に意味がありません。

4

1 に答える 1

2

Oboe の問題は、Oboe が JSON をストリーミングするという事実に基づいているため、promise の数を事前に知ることはできないため、Promise.all事前に責任を負うことはできません。メソッドで promise を返すことができるように、Oboe を「約束」することができます。

通常、RxJS を使用してイベント エミッターからストリームを自動的に作成します。RxJS のメソッドは既に promise を返し、それを集約することができます。ただし、ここではサードパーティのライブラリは必要なく、教育的価値も低いため、自分で実装しましょう。

function addMap(oboe) { 
  oboe.map = function(selector, mapper){
    var promises = [];
    return new Promise(function(resolve, reject){ // create a new promise
      oboe.node(selector, function(match){
        var result = mapper(match); // get result
        // signal that we're handling the rejection to make sure it's not handled.   
        result.catch(function(){});
        promises.push(result);
      });
      oboe.fail(reject); 
      oboe.done(function(){ resolve(promises); });
   });
  };
}

これにより、次のことが可能になります。

var o = oboe("foo");
addMap(o);
o.map("items.*", item => downloadItem(item)).then(result => {
   // handle result here
}); 

あなたのsetTimeout問題は非常に不自然です。大多数の人は、実際にはこのようなコードを書きません。実際には、そうするように強制する API (Oboe.js の例など) に対して作業しない場合、エラー ハンドラーを非同期的に追加することは非常にまれなユース ケースです。

本当に奇妙なこと: 最新のブラウザーは異なる動作をします

これは、Firefox が未処理の拒否を検出するために GC を使用し、Chrome がタイマーを使用するためです。thenこれは実装の詳細です。唯一の保証は、マイクロタスク内 (同期的に、または同じターンで実行される) にアタッチされている場合、エラーがログに記録されないことです。

于 2015-10-20T12:49:04.027 に答える