我有一个元素,我希望将其作为请求的HTML流填充,而不是等待完整的响应。事实证明这非常困难。
我尝试的事情:
milestoneNode.insertAdjacentHTML('beforebegin', text)
如果这样可行,那就太可爱了。不幸的是,具有古怪解析的元素会破坏它 - 例如<p>
和<table>
。得到的DOM可以被称为Dada。
Google incremental-dom
似乎最有希望,但其patch()
操作始终从容器节点的开头重新启动。不知道如何&#34;冻结&#34;它到位了。
这也包含了在JavaScript中至少进行HTML标记化的行李,并且某些实际的树构建必须发生,除非一个服务格式良好的XHTML5。 (没有人这样做。)重新实现 浏览器的 HTML解析器似乎是一个迹象,我已经犯了可怕的错误。
document.write()
我很绝望。具有讽刺意味的是,这位古老的笨蛋们几乎我所需要的行为,没有&#34;扔掉现有的页面&#34;的事情。
innerHTML
击败流媒体点,因为最终整个响应都被保存在内存中。还有重复的序列化开销。
从好的方面来说,它确实有效。但肯定有更好的方法吗?
答案 0 :(得分:2)
Jake Archibald figured out a silly hack to get this behavior in browsers today。他的示例代码说它比我更好:
// Create an iframe:
const iframe = document.createElement('iframe');
// Put it in the document (but hidden):
iframe.style.display = 'none';
document.body.appendChild(iframe);
// Wait for the iframe to be ready:
iframe.onload = () => {
// Ignore further load events:
iframe.onload = null;
// Write a dummy tag:
iframe.contentDocument.write('<streaming-element>');
// Get a reference to that element:
const streamingElement = iframe.contentDocument.querySelector('streaming-element');
// Pull it out of the iframe & into the parent document:
document.body.appendChild(streamingElement);
// Write some more content - this should be done async:
iframe.contentDocument.write('<p>Hello!</p>');
// Keep writing content like above, and then when we're done:
iframe.contentDocument.write('</streaming-element>');
iframe.contentDocument.close();
};
// Initialise the iframe
iframe.src = '';
虽然将
<p>Hello!</p>
写入iframe,但它会显示在父文档中!这是因为解析器维护一堆打开的元素,新创建的元素被插入其中。我们移动<streaming-element>
并不重要,它只是有效。
答案 1 :(得分:1)
您可以使用fetch()
,处理Response.body
ReadableStream
; TextDecoder()
let decoder = new TextDecoder();
function handleResponse(result) {
element.innerHTML += decoder.decode(result.value);
return result
}
fetch("/path/to/resource/")
.then(response => response.body.getReader())
.then(reader => {
return reader.read().then(function process(result) {
if (result.done) {
console.log("stream done");
return reader.closed;
}
return reader.read().then(handleResponse).then(process)
})
.then(function() {
console.log("stream complete", element.innerHTML);
})
.catch(function(err) {
console.log(err)
})
});