Javascript 加载文件后,如何将承诺错误传播到更高的承诺级别?

Javascript 加载文件后,如何将承诺错误传播到更高的承诺级别?,javascript,asynchronous,error-handling,promise,bluebird,Javascript,Asynchronous,Error Handling,Promise,Bluebird,我正在使用一个异步脚本加载器工作,我正在努力将错误传递到可以捕获它的地方 加载文件时,我调用名为declare的方法,如下所示: declare("storage", [ {"name": 'util', "src": '../src/util.js'} ], function (util) { var storage = {}; //...stuff with util return storage; }); 声明为: declare = func

我正在使用一个异步脚本加载器工作,我正在努力将错误传递到可以捕获它的地方

加载文件时,我调用名为
declare
的方法,如下所示:

  declare("storage", [
    {"name": 'util', "src": '../src/util.js'}
  ], function (util) {
    var storage = {};
    //...stuff with util
    return storage;
  });
声明
为:

declare = function (name, dependency_list, callback) {
   var resolver;

   // digest promises returned for each module
   function digestDependencyArray(my_dependency_array) {
     var i, len, response_array;

     len = my_dependency_array.length;
     for (i = 0, response_array = []; i < len; i += 1) {
       response_array[i] = my_dependency_array[i];
     }

     return Promise.all(response_array);
   }

   // resolve request promise
   function resolveDependencyArray(my_fullfillment_array) {
      var return_value = callback.apply(window, my_fullfillment_array);

      // window.exports must be used when integrating commonjs modules
      if (!return_value) {
        return_value = window.exports;
      }

      resolver(return_value);
   }

   // START: set callback to (resolved) callback or new promise
   my_lib.callback_dict[name] = my_lib.callback_dict[name] ||
      new Promise(function (resolve) {
        resolver = resolve;
        if (dependency_list.length === 0) {
          return resolver(callback.apply(window));
        }

        return request(dependency_list)
          .then(digestDependencyArray)
          .then(resolveDependencyArray)
          // DON'T CATCH HERE...
          .catch(console.log);
      });
  };
request
将在一个promise中加载文件,该promise在加载文件时得到解析,并以回调的形式运行文件内容,然后调用上述
declare
方法。不知何故,我的错误在途中丢失了(代码)。让我们看看我是否能在某处捕捉到它

编辑2
更改为此内部声明:

function resolveDependencyArray(my_fullfillment_array) {
  var return_value = callback.apply(window, my_fullfillment_array);

  if (!return_value) {
    return_value = window.exports;
  }
  return return_value;
}

function handler() {
  if (dependency_list.length === 0) {
    Promise.resolve(callback.apply(window));
  } else {
    return request(dependency_list)
      .then(digestDependencyArray)
      .then(resolveDependencyArray)
      .catch(function (e) {
        reject(e);
      });
  }
}

clappjs.callback_dict[name] = clappjs.callback_dict[name] || handler();
虽然我没有收到错误,但请求多个模块不起作用,因为返回的模块未定义,因此:

request(["foo", "bar", "baz"]).spread(function (foo, bar, baz) {
 console.log(foo);  // undefined
 console.log(bar);  // {} OK
 console.log(baz);  // undefined
});

与新承诺相比,加载后正确返回文件。

您需要重新显示错误

.catch(function(e) {
  console.log(e); // calling it as a method, btw
  throw e;
})
在添加
.catch(console.log)
之前,您还可以尝试使用或返回链中的承诺


此外,您正在使用,而实际上不应该使用。只要使用你已经拥有的承诺!您似乎想这样做:

my_lib.callback_dict[name] = my_lib.callback_dict[name] || (
  dependency_list.length === 0
  ? Promise.resolve()
  : request(dependency_list)
      .then(digestDependencyArray)
      .then(resolveDependencyArray) // don't call a global `resolver()`
                                    // just `return` the value!
);
提供
请求([])
将返回
[]
回调
愉快地接受
[]
,然后
声明()
应简化如下:

declare = function(name, dependency_list, callback) {
    if(!my_lib.callback_dict[name]) {
        my_lib.callback_dict[name] = request(dependency_list).then(function(arr) {
            return Promise.all(arr);
        }).then(function(arr) {
            return callback.apply(window, arr) || window.exports;
        });
    }
    return my_lib.callback_dict[name];
};
然后确保
callback
返回错误的内容,例如
null
用于应使用
窗口的条件。导出

我可能做了一两个非自愿的假设,但我相信类似于上述的东西应该能起作用

就我个人而言,我会处理回电话中的任何错误

declare(name, dependency_list, callback).then(handleSucces).then(null, handleError);

通过在单独的
中处理成功和失败,那么
handleSuccess中抛出的任何未捕获错误也将被
handleError

捕获,我猜您最初想做的是
新承诺(函数(解析,拒绝){…捕获(拒绝);}
然而,这是一个反模式:-/感谢反模式示例。关于抛出的一个问题:我似乎在抛出,但我在其他地方捕捉到了错误。请参见上面的编辑。是的,对,在使用
Promise
构造函数的原始代码中,这是一个未经处理的拒绝,因为该承诺不会发生任何事情。您需要调用
拒绝(e)
而不是抛出。但是,在固定代码中,被拒绝的承诺被分配给
回调dict
,当该承诺是
请求()
ed。或者它不是这样工作的吗?拒绝为我解决了这个问题。我不确定我是否理解这个代码段,因为我为每个正在加载的文件设置了一个
新的
承诺。如果在承诺得到解决之前加载了文件,并且返回值被返回(在
clapjs.callback\u dict[name]
)。如果它需要加载并且没有依赖项,我可以立即将新承诺设置为已解决。如果它有依赖项,则需要首先加载这些承诺,并将其包含在最终解决中。因此,我不明白为什么我可以在没有“新建”的情况下执行此操作承诺。是的,您通常会希望在某个地方创建一个
新承诺
,通常用于加载文件。但不是在这个地方,您可以在没有依赖项的情况下创建一个已履行的承诺(
Promise.resolve()
),也可以只编写一个
请求()的承诺
通过调用
.then()
返回到一个新的构造函数。不要在此处使用
Promise
构造函数!重试(参见上面的edit2),但我没有得到好的结果,因为一些请求的模块返回了未定义的
,而使用我的原始代码总是返回正确的模块。我现在很好,如果有时间,我会调查并发布完整的示例,如果你想再次尝试。谢谢!
declare(name, dependency_list, callback).then(handleSucces).then(null, handleError);