javascript - 如何调试 "TypeError: A promise cannot be resolved with itself"

标签 javascript debugging asynchronous es6-promise

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

类型错误: promise 无法自行解决

然而,它没有提供源代码行号或其他引用,即使现在发生该类型错误也给我带来麻烦。老实说,调试异步事物(就像卓越的 Promise)被证明是一个挑战。知道我如何追踪这个 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)调试窗口的控制台输出的屏幕截图,遗憾的是它并不总是显示行号

the line number is n o t  alwyas shown

最佳答案

当使用不同 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 毫秒后调用,但 secondPromise 仅在 1000 毫秒后才真正解析。 2000 毫秒,因为 existingProm(在 2000 毫秒后解析)已传递给 resolve

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

但是,如果您将正在构造的 Promise 传递给用于构造 Promise 的同一个 resolve,那么您就创建了一个循环 - resolve(promise); 意味着构造的 Promise 仅在 promise 解析后才会解析。但是promise构造了Promise。解释器看到这种循环情况并抛出错误(通过拒绝 Promise)。

任何类型的循环 Promise 循环都可能导致此错误。例如,如果 prom1 使用 prom2 调用其 resolve,并且 prom2 调用其 resolve > 与prom1:

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 的内容,或者从 .then 返回的内容创造了 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.dir(e.stack));

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

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

对应于这一行:

resolve(prom1);

这确实是 prom1 循环依赖的根源。

关于javascript - 如何调试 "TypeError: A promise cannot be resolved with itself",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57018864/

相关文章:

javascript - ES6解构函数参数-命名根对象

javascript - 无法安装discord.js/找不到模块discord.js

c# - 无法在 C# 中异步运行方法

javascript - 嵌套异步函数,最佳实践

python - 同时使用 Tornado 和 Twisted

javascript - Angular Ng-重复有序列表

javascript - 为什么 Chrome 不显示我的 User Timing API 使用情况的任何数据?

ruby - 如何在 Ruby 2.0 中使用调试器?

debugging - 将全局变量用于调试代码是否可以接受

javascript - 如何调试javascript?