繁体   English   中英

如何调试“类型错误:无法用自身解决承诺”

[英]How to debug "TypeError: A promise cannot be resolved with itself"

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

TypeError: A promise cannot be resolved with itself

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

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

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

但这只是证实了用自身解决promise这样的事情确实是可能发生的,并且随后会导致promise由于发生的错误而被拒绝;

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)调试窗口控制台输出的屏幕截图,显示遗憾的是它并不总是显示行号

行号不总是显示

当使用不同的Promise调用 Promise 构造函数中的resolve时,构造的 Promise 解析为的值将是 Promise 传递给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'); });

正如你在上面的代码片段中看到的,虽然secondPromiseresolve在 1000 ms 之后被调用,但是secondPromise只在 2000 ms 之后才真正解析,因为existingProm (它在 2000 ms 之后解析)被传递给了resolve

这就像从.then内部返回一个 Promise -下一个.then将解析为返回的 Promise 解析为的值。

但是,如果您将正在构造的 Promise 传递给用于构造 Promise 的相同resolve ,则您已经创建了一个循环 - resolve(promise); 将意味着构建无极只解析一次promise做出决议。 promise构造的Promise。 解释器看到这种循环情况并抛出错误(通过拒绝 Promise)。

任何类型的循环 Promise 循环都可能导致此错误。 例如,如果prom1调用它的resolveprom2 ,并prom2调用它的resolveprom1

 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));

要调试这样的错误,请查看生成错误的 Promise,并检查它的resolve是用什么调用的,或者从创建 Promise 的.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));

在我的机器上,这显示错误发生

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

对应于这一行:

resolve(prom1);

这确实是prom1循环依赖的prom1

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM