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 开发者版中,一切正常,没有错误消息,而在 Chrome 中,我被Uncaught (in promise). 在 Chrome 中,如果你写Promise.reject();的时候没有捕捉到,你会立即收到消息。在 Firefox 和 Safari 中没有任何反应。

那么解决这个问题的方法是什么?忽略消息?我的意思是,如果这种行为真的在官方承诺规范中,那么异步代码中的承诺对我来说就没有意义了。

4

1 回答 1

2

您的双簧管问题是基于双簧管流式传输 JSON 的事实,因此我们无法事先知道有多少承诺,因此我们无法Promise.all提前承担责任。我们可以“承诺”双簧管能够在其方法中返回承诺。

通常,我会使用 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 回答