问题描述
我正在尝试在div中显示console.log
输出。我是通过覆盖console.log
函数
当我使用原始的console.log
时,诺言会在控制台中显示为(请参见下面的代码中的1。):
Promise { <state>: "fulfilled",<value>: undefined }
当我超越它时,在div中得到::
[object Promise]
(请参见下面的代码中的2。)
您如何调整以下代码,以在{main“ div中显示<state>
属性?
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生态系统)。如果可以在一个简单的示例中进行复制,我可能会写一个后续问题。
解决方法
您可以使用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 { <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",() => { 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>
,
一种更简单的方法来兑现承诺的真实价值可能是:
async function myLog(val) {
console.log(await val);
}
await
确保兑现承诺,但也可以很好地通过非承诺。