覆盖 console.log 时如何显示 Promise 对象的状态和值

ato*_*3ls 5 html javascript overriding promise console.log

console.log我正在尝试在 div 中显示输出。我通过重写console.log函数来做到这一点

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

Promise { <state>: "fulfilled", <value>: undefined }
Run Code Online (Sandbox Code Playgroud)

当我覆盖它时,我在 div: 中得到:

 [object Promise]
Run Code Online (Sandbox Code Playgroud)

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

您将如何调整以下代码以使该<state>属性显示在“main”div 中?

Promise { <state>: "fulfilled", <value>: undefined }
Run Code Online (Sandbox Code Playgroud)
 [object Promise]
Run Code Online (Sandbox Code Playgroud)

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

ibr*_*rir 3

您可以使用另一个 SO 答案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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

解释:

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

如果我们收到错误(意味着catch回调被调用),则承诺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) {
  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
  }
}
Run Code Online (Sandbox Code Playgroud)
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);
})();
Run Code Online (Sandbox Code Playgroud)