覆盖 console.log 时如何显示 promise 对象的状态和值
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>
关于我为什么要问的注释:我有一个承诺在桌面浏览器而不是移动浏览器中解析的代码。我正在尝试对此进行调试(没有一致的移动桌面 OS 生态系统)。如果我可以在一个简单的例子中复制它,我可能会写一个后续问题。
您可以使用 中的这个技巧来处理 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 { <state>: "${ state.state }"${ state.state === "fulfilled" ? ', <value>: ' + 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
因为它将承诺包装在另一个承诺中。这是您唯一可以做到的方法。
解释:
诀窍是 race
承诺 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) {
let divconsole = document.getElementById('main');
for (let arg of args) {
if (arg instanceof Promise) {
let state = await promiseState(arg);
divconsole.innerHTML += `Promise { <state>: "${ state.state }"${ state.state === "fulfilled" ? ', <value>: ' + 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>
将任何东西 promise-like 转换为其真实值的更简单方法可能是:
async function myLog(val) {
console.log(await val);
}
await
确保 promise 得到解决,但也可以很好地通过 non-promises。
我正在尝试在 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>
关于我为什么要问的注释:我有一个承诺在桌面浏览器而不是移动浏览器中解析的代码。我正在尝试对此进行调试(没有一致的移动桌面 OS 生态系统)。如果我可以在一个简单的例子中复制它,我可能会写一个后续问题。
您可以使用 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 { <state>: "${ state.state }"${ state.state === "fulfilled" ? ', <value>: ' + 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
因为它将承诺包装在另一个承诺中。这是您唯一可以做到的方法。
解释:
诀窍是 race
承诺 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) {
let divconsole = document.getElementById('main');
for (let arg of args) {
if (arg instanceof Promise) {
let state = await promiseState(arg);
divconsole.innerHTML += `Promise { <state>: "${ state.state }"${ state.state === "fulfilled" ? ', <value>: ' + 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>
将任何东西 promise-like 转换为其真实值的更简单方法可能是:
async function myLog(val) {
console.log(await val);
}
await
确保 promise 得到解决,但也可以很好地通过 non-promises。