如何调试“ TypeError:一个承诺无法自身解决”

时间:2019-07-13 11:45:44

标签: javascript debugging asynchronous es6-promise

在我的浏览器中的javascripts webconsole中,我看到了错误消息:

TypeError: A promise cannot be resolved with itself

但是,它没有提供源代码行号或其他参考,即使在现在出现错误类型的情况下,也给我带来麻烦。老实说,调试异步事物(就像卓越的Promises)是一个挑战。知道我如何追踪,发生TypeError的原因和地点吗?

我所做的是能够引发相同的错误消息 使用此代码:

var promise = new Promise((resolve,reject)=>{
  setTimeout(()=>{
    resolve(promise);
  },0);
});

但这仅确认了解决 承诺本身确实是可能发生的事情 并导致随后的诺言被拒绝 由于发生错误;

console.log(promise);
// prints: Promise { <state>: "rejected" }

理想的答案将提供某种指导(步骤) 有助于显示javascript源代码的哪一部分 实际上是导致错误的原因。

一个有用的答案也可以简单列出所有方式(其他 比我提供的示例代码要少 同样的错误。

已更新 来源中唯一发生new Promise(callback)的地方是这样的,在我看来不会引起圆形图案。

function xhrGet(url){    
    return new Promise((resolve,reject)=>{    
        var xhr = new XMLHttpRequest();    
        xhr.open("GET",url);    
        xhr.responseType = "arraybuffer";    
        xhr.addEventListener("load",function(){    
            resolve(xhr.response);    
        });    

        xhr.addEventListener("error",function(er){    
            reject(er);    
        });    
        xhr.send();    
    });    
}   

似乎是恕我直言,不太可能是罪魁祸首。

此处是Firefox(版本68)调试窗口的控制台输出的屏幕快照,显示它不幸地并不总是显示行号

the line number is n o t  alwyas shown

1 个答案:

答案 0 :(得分:1)

当用 resolve调用Promise构造函数中的Promise时,构造的Promise解析为的值将是Promise传递到{{1} }解决。

resolve

如上面的代码片段所示,尽管const existingProm = new Promise(resolve => { setTimeout(() => { console.log('existing promise resolving'); resolve(); }, 2000); }); var secondPromise = new Promise((resolve,reject)=>{ setTimeout(()=>{ console.log("second promise's resolve being called"); resolve(existingProm); },1000); }); secondPromise.then(() => { console.log('second promise fulfilled'); });的{​​{1}}是在1000毫秒后调用的,但是secondPromise实际上是在2000毫秒后才解析的,因为resolve (在2000毫秒后解析)传递给secondPromise

这就像从existingProm内部返回Promise一样- next resolve将解析为返回的Promise所解析的值。

但是,如果您将要构造的Promise传递给用于构造Promise的同一.then,则您已经创建了一个循环-.then表示构造的Promise仅解析一次resolve解决。但是resolve(promise); 构成了Promise。解释器看到了这种循环情况并抛出错误(通过拒绝Promise)。

任何种类的循环Promise循环都可能导致此错误。例如,如果promisepromise调用其prom1,而resolveprom2调用其prom2

resolve

要调试像这样的错误,请查看产生错误的Promise,并检查调用其prom1的内容或从创建Promise的const prom1 = new Promise(resolve => { setTimeout(() => { console.log('prom1 resolve being called'); resolve(prom1); }, 1000); }); const prom2 = new Promise(resolve => { setTimeout(() => { console.log('prom2 resolve being called'); resolve(prom2); }, 1000); }); prom1.catch((e) => console.log(e.message));返回的内容。您在某处有一个圆形链。例如:

resolve

在我的机器上,这表明发生了错误

  

https://stacksnippets.net/js:16:5

对应于此行:

.then

这确实是const prom1 = new Promise(resolve => { setTimeout(() => { console.log('prom1 resolve being called'); resolve(prom1); }, 1000); }); const prom2 = new Promise(resolve => { setTimeout(() => { console.log('prom2 resolve being called'); resolve(prom2); }, 1000); }); prom1.catch((e) => console.dir(e.stack));循环依赖的来源。