Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么新承诺的reject()会在可怕的“中丢失堆栈跟踪”;未兑现的(承诺中的)“;错误_Javascript_Angular_Es6 Promise - Fatal编程技术网

Javascript 为什么新承诺的reject()会在可怕的“中丢失堆栈跟踪”;未兑现的(承诺中的)“;错误

Javascript 为什么新承诺的reject()会在可怕的“中丢失堆栈跟踪”;未兑现的(承诺中的)“;错误,javascript,angular,es6-promise,Javascript,Angular,Es6 Promise,在Angular的github发行版中搜索“Uncaught(in promise)”,google或stackoverflow上的此处会产生很多非常具体的结果,但我的问题要宽泛一些(由于结果激增,我不知道这是否是重复) 前提:在我的代码中的某个地方,我有一个未预料到的拒绝承诺(Angular 4.4.4) 案例: 案例1:简单拒绝 在MyComponent中: 在控制台中产生这个(很好,我可以看到它来自哪里): 案例2:新承诺,抛出错误 在MyComponent中: 在控制台中产生这种效果(更

在Angular的github发行版中搜索“Uncaught(in promise)”,google或stackoverflow上的此处会产生很多非常具体的结果,但我的问题要宽泛一些(由于结果激增,我不知道这是否是重复)

前提:在我的代码中的某个地方,我有一个未预料到的拒绝承诺(Angular 4.4.4)

案例:

案例1:简单拒绝

在MyComponent中:

在控制台中产生这个(很好,我可以看到它来自哪里):

案例2:新承诺,抛出错误

在MyComponent中:

在控制台中产生这种效果(更好的是,在现场给出位置):

这也适用于链接,例如,以下内容在控制台中或多或少给出了相同的堆栈跟踪

ngOnInit() {


  const promise3 = new Promise((resolve, reject) => {
    throw new Error("baz");
  });
  const promise2 = new Promise((resolve, reject) => {
    resolve(promise3);
  });

  const promise1 = new Promise((resolve, reject) => {
    resolve(promise2);
  });

  promise1.then(p1=> console.log(p1));
}
案例3:使用拒绝(…)

在MyComponent中:

更改使用promise的reject方法时抛出错误(我假设这是非常常见的做法),会产生以下可怕的结果:

core.es5.js:1020 ERROR Error: Uncaught (in promise): baz
    at resolvePromise (zone.js:824)
    at resolvePromise (zone.js:795)
    at zone.js:873
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
    at Object.onInvokeTask (core.es5.js:3881)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (zone.js:192)
    at drainMicroTaskQueue (zone.js:602)
    at <anonymous>
core.es5.js:1020错误:未捕获(承诺中):baz
在resolvePromise(zone.js:824)
在resolvePromise(zone.js:795)
在zone.js:873
在ZoneDelegate.webpackJsonp…/../../../../../../zone.js/zone.js.ZoneDelegate.invokeTask(zone.js:425)
位于Object.onInvokeTask(core.es5.js:3881)
在ZoneDelegate.webpackJsonp…/../../../../../../zone.js/zone.js.ZoneDelegate.invokeTask(zone.js:424)
位于Zone.webpackJsonp…/../../../../../Zone.js/dist/Zone.js.Zone.runTask(Zone.js:192)
在drainMicroTaskQueue(zone.js:602)
在
问题

  • 为什么这次我看不到堆栈跟踪或错误的来源?(我假设这是因为JavaScript仅从抛出错误的位置生成堆栈跟踪?)

  • 如果是这样的话,使用显式拒绝而不是在新承诺中抛出新错误,这是一种不好的做法吗?有没有记录在案而我错过了

  • 有办法解决这个问题吗?(获取堆栈跟踪并继续使用reject(…)而不是抛出错误?,我假设没有)

  • 这是一个众所周知的问题/糟糕的做法,而我只是错过了备忘录


  • 部分回答了我自己的一个问题:

    如果我将案例#3改为:(包装在新的错误对象中)

    然后,令人惊讶的是,我确实得到了堆栈跟踪!(仅构造错误即可保存堆栈跟踪)

    顺便说一句。。。既然(我猜)我们大多数人都喜欢看堆栈跟踪而不是不看,那么为什么这里没有提到这是一个最佳实践呢

    编辑

    为了确保我不会忘记,我添加了这个缩小(
    reject:(原因:Error)=>void
    而不是
    any
    ),不确定这是否是一个很好的解决方案,因为它不能防止传递
    any
    ,但它可以帮助保护一些不传递
    错误的情况

    export {}
    
    declare global {
    
      interface PromiseConstructor {
        /**
         * A reference to the prototype.
         */
        readonly prototype: Promise<any>;
    
        /**
         * Creates a new Promise.
         * @param executor A callback used to initialize the promise. This callback is passed two arguments:
         * a resolve callback used resolve the promise with a value or the result of another promise,
         * and a reject callback used to reject the promise with a provided reason or error.
         */
        new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason: Error) => void) => void): Promise<T>;
    
      }
    }
    
    export{}
    宣布全球{
    接口承诺构造函数{
    /**
    *对原型的引用。
    */
    只读原型:Promise;
    /**
    *创造新的承诺。
    *@param executor用于初始化承诺的回调。此回调传递了两个参数:
    *使用值或其他承诺的结果解析承诺时使用的解析回调,
    *以及拒绝回调,用于以提供的原因或错误拒绝承诺。
    */
    新(执行人:(决定:(价值?:T |承诺)=>无效,拒绝:(原因:错误)=>无效)=>无效):承诺;
    }
    }
    
    尝试拒绝(新错误(“foo”)
    。您使用的承诺实现是什么?关于问题2:Oops,没有看到@Bergi的评论中说的正是这一点。保持清晰。。。
    ERROR Error: Uncaught (in promise): Error: foo
    Error: foo
        at my.component.ts:nn
        at new ZoneAwarePromise (zone.js:890)
        at MyComponent.webpackJsonp.../../../../../src/app/component/my.component.ts.LMyComponent.ngOnInit (my.component.ts:nn)
    
    ngOnInit() {
    
    
      const promise3 = new Promise((resolve, reject) => {
        throw new Error("baz");
      });
      const promise2 = new Promise((resolve, reject) => {
        resolve(promise3);
      });
    
      const promise1 = new Promise((resolve, reject) => {
        resolve(promise2);
      });
    
      promise1.then(p1=> console.log(p1));
    }
    
    ngOnInit() {
      new Promise((resolve, reject) => {
        reject("foo");
      }).then(() => {
        console.log("ain't gonna happen");
      });
    }
    
    core.es5.js:1020 ERROR Error: Uncaught (in promise): baz
        at resolvePromise (zone.js:824)
        at resolvePromise (zone.js:795)
        at zone.js:873
        at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
        at Object.onInvokeTask (core.es5.js:3881)
        at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:424)
        at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.runTask (zone.js:192)
        at drainMicroTaskQueue (zone.js:602)
        at <anonymous>
    
    ngOnInit() {
      new Promise((resolve, reject) => {
        reject(new Error("foo"));
      }).then(() => {
        console.log("ain't gonna happen");
      });
    }
    
    export {}
    
    declare global {
    
      interface PromiseConstructor {
        /**
         * A reference to the prototype.
         */
        readonly prototype: Promise<any>;
    
        /**
         * Creates a new Promise.
         * @param executor A callback used to initialize the promise. This callback is passed two arguments:
         * a resolve callback used resolve the promise with a value or the result of another promise,
         * and a reject callback used to reject the promise with a provided reason or error.
         */
        new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason: Error) => void) => void): Promise<T>;
    
      }
    }