简体   繁体   English

覆盖 console.log 时,您将如何显示承诺对象的状态和值

[英]How would you display a promise object's state and value when overriding console.log

I'm attempting to display the console.log output in a div.我试图在 div 中显示console.log输出。 I'm doing this by overriding the console.log function我通过覆盖console.log函数来做到这一点

When I use the original console.log , a promise displays, in the console as (see 1. in code below):当我使用原始的console.log ,在控制台中会显示一个承诺(参见下面代码中的 1.):

Promise { <state>: "fulfilled", <value>: undefined }

When I over-ride it I get, in the div: :当我越过它时,在 div 中:

 [object Promise]

(see 2. in code below) (参见下面代码中的 2.)

How would you adjust the following code to have the <state> property displayed in the "main" div?您将如何调整以下代码以使<state>属性显示在“主”div 中?

 const pause = sec => new Promise(r => setTimeout(r, 1000 * sec)) // 1. Original console.log ;(async function(){ await new Promise(resolve => document.addEventListener('DOMContentLoaded', resolve)); let x = pause(0.5) console.log(x) await x; console.log(x) })(); // 2. Overridden console.log ;(async function(){ await new Promise(resolve => document.addEventListener('DOMContentLoaded', resolve)); await pause(1) let divconsole = document.getElementById('main'); // Override console.log: console.log = function () { for (let i = 0; i < arguments.length; i++) { if (typeof arguments[i] === 'object') { divconsole.innerHTML += 'console.log arg ' + String(i) + ': ' + String(arguments[i]) + '<br>'; } } } let y = pause(0.5) console.log(y) await y; console.log(y) })();
 <div id="main" style="width:100%;height:auto;background-color:lightblue;"> </div>

A note on why I'm asking: I have code with a promise that resolves in a desktop browser and not in a mobile browser.关于我为什么要问的说明:我有一个承诺在桌面浏览器中而不是在移动浏览器中解析的代码。 I'm attempt to debug this (without consistent mobile-desktop OS ecosystem).我正在尝试对此进行调试(没有一致的移动桌面操作系统生态系统)。 I might write a follow up question if I can replicate it in a simple example.如果我可以在一个简单的例子中复制它,我可能会写一个后续问题。

You can use this trick from this other SO answer to handle the arguments that are of type Promise like so.您可以使用this other SO answer中的这个技巧来处理像这样的Promise类型的参数。 The trick requires the custom console.log to be asynchronous like so:该技巧要求自定义console.log像这样异步:

function promiseState(p) {
    const t = {};
    return Promise.race([p, t])
      .then(v =>
        (v === t) ? { state: "pending" } : { state: "fulfilled", value: v },
        () => { state: "rejected" }
      );
}

console.log = async function(...args) {
  for (let arg of args) {
    if (arg instanceof Promise) {
      let state = await promiseState(arg);
      divconsole.innerHTML += `Promise { &lt;state&gt;: "${ state.state }"${ state.state === "fulfilled" ? ', &lt;value&gt;: ' + state.value : '' } }<br>`;
    } else if (typeof arg === 'object') {
      divconsole.innerHTML += 'console.log arg:  ' + String(arg) + '<br>';
    }
    // add more else-ifs to handle strings, numbers, booleans, ... etc
  }
}

The custom console.log needs to be asynchronous because it wraps the promise in another promise.自定义console.log需要是asynchronous因为它将承诺包装在另一个承诺中。 This is the only way you can do it.这是您可以做到的唯一方法。

Explanation:解释:

The trick is to race the promise p against a resolved one (that yields an object {} ), if the promise p is already fulfilled its value will be used and since its value can't be the same as that of the other promise (the one we are racing against, the one that yields {} ), we determine that the promise has fulfilled.诀窍是将承诺p与已解决的(产生一个对象{}race ,如果承诺p已经实现,则将使用其值,并且由于其值不能与另一个承诺的值相同(与我们竞争的那个,产生{}那个,我们确定承诺已经实现。 If the value we get is that of the other promise (the object {} ) meaning that our resolved promise won the race, we can be sure that the promise p has not yet fulfilled.如果我们得到的值是另一个承诺(对象{} )的值,这意味着我们解决的承诺赢得了比赛,我们可以确定承诺p尚未实现。

If we get an error (meaning the catch callback gets called), the the promise p is rejected.如果我们得到一个错误(意味着catch回调被调用),promise p被拒绝。

Demo:演示:

 function promiseState(p) { const t = {}; return Promise.race([p, t]) .then(v => (v === t) ? { state: "pending" } : { state: "fulfilled", value: v }, () => { state: "rejected" } ); } console.log = async function(...args) { let divconsole = document.getElementById('main'); for (let arg of args) { if (arg instanceof Promise) { let state = await promiseState(arg); divconsole.innerHTML += `Promise { &lt;state&gt;: "${ state.state }"${ state.state === "fulfilled" ? ', &lt;value&gt;: ' + state.value : '' } }<br>`; } else if (typeof arg === 'object') { divconsole.innerHTML += 'console.log arg: ' + String(arg) + '<br>'; } } } const pause = sec => new Promise(r => setTimeout(r, 1000 * sec)); ;(async function() { await new Promise(resolve => document.addEventListener('DOMContentLoaded', resolve)); await pause(1); let divconsole = document.getElementById('main'); let y = pause(0.5); await console.log(y); await y; await console.log(y); })();
 <div id="main" style="width:100%;height:auto;background-color:lightblue;"></div>

An easier way to cast anything promise-like to it's real value might be:将任何类似承诺的东西转化为真正价值的更简单方法可能是:

async function myLog(val) {
  console.log(await val);
}

await ensures that promises are resolved, but also passes through non-promises just fine. await确保承诺得到解决,但也通过非承诺就好了。

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

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