简体   繁体   中英

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

In javascripts webconsole in my browser I read the Error message:

TypeError: A promise cannot be resolved with itself

which however does not furnish a source code line number or other reference, giving me trouble to even now where that type Error occurs. In all honesty debuging asynchronous things (as are par excellence Promises) turns out to be a challeng. Any idea how I can track down, what and where this TypeError happens?

What I have done is to be able to provoke the same error message using this code:

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

But this does only confirm that such a thing as resolving a promise with itself is indeed something that can occur and which leads subsequenty to the promise being rejected due to the occuring error;

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

An ideal answer would provide some sort of guide (steps) that help to show which part of the javascript source code is actually causes the error.

A helpful answer could also list simply all the ways (other than the one I have provided example code for) that can lead to the very same error.

Updated The only place in the source, where a new Promise(callback) occurs looks like this, and appears to me cannot cause a circular pattern.

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

It seems imho, unlikely to be the culprit.

here a screenshot of the console output of the debug window of Firefox(ver 68) showing that it sadly does not always show the line number

行号不总是显示

When resolve in a Promise constructor is called with a different Promise , the value that the constructed Promise resolves to will be what that Promise passed into resolve resolves to.

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

As you can see in the above snippet, although secondPromise 's resolve is called after 1000 ms, the secondPromise only actually resolves after 2000 ms, because existingProm (which resolves after 2000 ms) was passed to the resolve .

It's just like returning a Promise from inside a .then - the next .then will resolve to the value of what the returned Promise resolved to.

But if you pass the Promise you're constructing to the same resolve that's being used to construct the Promise, you've created a cycle - resolve(promise); will mean that the constructed Promise resolves only once promise resolves. But promise is that constructed Promise. The interpreter sees this circular situation and throws an error (by rejecting the Promise).

Any sort of circular Promise cycle can result in this error. For example, if prom1 calls its resolve with prom2 , and prom2 calls its resolve with 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));

To debug an error like this, look at the Promise that generates the error, and examine what its resolve was called with, or what was returned from the .then that created the Promise. You have a circular chain in there somewhere. For example:

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

On my machine, this shows the error as occurring

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

which corresponds to this line:

resolve(prom1);

which is indeed the source of the circular dependency for prom1 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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