繁体   English   中英

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

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

我试图在 div 中显示console.log输出。 我通过覆盖console.log函数来做到这一点

当我使用原始的console.log ,在控制台中会显示一个承诺(参见下面代码中的 1.):

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

当我越过它时,在 div 中:

 [object Promise]

(参见下面代码中的 2.)

您将如何调整以下代码以使<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>

关于我为什么要问的说明:我有一个承诺在桌面浏览器中而不是在移动浏览器中解析的代码。 我正在尝试对此进行调试(没有一致的移动桌面操作系统生态系统)。 如果我可以在一个简单的例子中复制它,我可能会写一个后续问题。

您可以使用this other SO answer中的这个技巧来处理像这样的Promise类型的参数。 该技巧要求自定义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
  }
}

自定义console.log需要是asynchronous因为它将承诺包装在另一个承诺中。 这是您可以做到的唯一方法。

解释:

诀窍是将承诺p与已解决的(产生一个对象{}race ,如果承诺p已经实现,则将使用其值,并且由于其值不能与另一个承诺的值相同(与我们竞争的那个,产生{}那个,我们确定承诺已经实现。 如果我们得到的值是另一个承诺(对象{} )的值,这意味着我们解决的承诺赢得了比赛,我们可以确定承诺p尚未实现。

如果我们得到一个错误(意味着catch回调被调用),promise p被拒绝。

演示:

 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>

将任何类似承诺的东西转化为真正价值的更简单方法可能是:

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

await确保承诺得到解决,但也通过非承诺就好了。

暂无
暂无

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

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