【问题标题】:Synchronously manipulate DOM?同步操作 DOM?
【发布时间】:2018-03-03 02:44:14
【问题描述】:

我目前正在开发一个自定义浏览器,它几乎可以运行 带有 Promises 的普通 ES5,并且根本不支持非本机代码。 该浏览器旨在模拟特定硬件的性能,其处理能力不是很好。此外,我的应用程序大小限制非常短。

考虑到这一点以及在同一个窗口中显示不同视图的任务,一次一个,每次使用应用程序时只有一次,我想出了重新加载的想法只有一个 iframe,而不是整个页面。

为此,我编写了以下代码:

function loadFrame(page){
    return new Promise(function(resolve, reject){
        var iframe = document.createElement('iframe');
        iframe.classList.add('hidden');
        iframe.src = page;

        resolve(iframe);
    });
}
function appendTo(elem, parentId){
    return new Promise(function(resolve, reject){
        var parentNode = document.getElementById(parentId);
        parentNode.appendChild(elem);

        resolve(elem);
    });
}
function robOf(elem, id){
    return new Promise(function(resolve, reject){
        var parent = elem.parentNode;
        var doc = elem.contentDocument; // body hasn't loaded so...
        var toImport = doc.getElementById(id); // ... this returns undefined...
        var imported = parent.importNode(toImport, true); //... thus breaking it here
        parent.removeChild(elem);

        resolve(imported);
    });
}

loadFrame('example/myPage.htm')
.then(function(elem){ return appendTo(elem, 'myParentId') })
.then(function(parent){ return robOf(parent, 'myElemId') })
.then(doSomething);

它背后的想法很简单:

  • 创建一个 iframe;
  • 用本地文件加载它;
  • 在 iframe 的文档中查找给定的元素;
  • 将该给定元素导入我的页面文档;
  • 删除 iframe。

但是,它变砖了。有时iframe 只是没有及时加载,所以当我定义doc 时,它的主体是空的,我在.importNode() 上传递undefined,炸毁了整个东西。认为它应该是一个异步执行问题,我将函数包装在 Promises 中并最终得到了这样的代码,但问题仍然存在。 我想确切地知道我对 Promises 有什么误解,为什么代码不工作以及如何纠正它,最好不使用 setTimeout()。

【问题讨论】:

  • 只是说,你可以做elem.contentDocument --- 不能解决你的问题。
  • 这个自定义浏览器有事件处理程序吗?因为iframes 有一个load 事件你可以监听...
  • 我不太明白您的情况如何阻止您使用正常的 DOM 操作。假设您有一个文档全局范围,那么您是否可以跟踪您的应用程序状态并只是...更新 DOM 以反映用户应该查看的状态?为什么在这里需要 iframe?
  • @zevee:我会用它更新我的代码。谢谢。
  • @MikeMcCaughan:是的,它有。没有想到,会尽快尝试这个解决方案。

标签: javascript dom promise ecmascript-5


【解决方案1】:

您可以在<iframe> 上侦听load 事件,以确保iframe 永远不会是undefined

function loadFrame(page){
    return new Promise(function(resolve, reject){
        var iframe = document.createElement('iframe');
        iframe.addEventListener('load', function(e) {
            resolve(this);
        });
        iframe.classList.add('hidden');
        iframe.src = page;
    });
}

此外,在您的函数上调用 .bind 也可能会导致您的某些问题。

改用.then(function(x) { return functionCall(x,p2,p3) });

【讨论】:

  • 如果我这样做了,下一个 Promise 会等到 load 函数解析吗?关于bind,我真的不明白它对我的情况有何影响。我刚刚得到了搜索如何将参数传递给 Promise 的基础,仅此而已。我将按照您的方式更改代码。 (这比绑定的东西读起来好多了)
  • 尝试使用柯里化你的函数而不是绑定和传递参数,我想更具可读性
  • @AngelSalazar:我想没有胖箭头的咖喱有点奇怪。由于所有return function(p){ ... } 的东西,代码变得非常金字塔和冗长。
猜你喜欢
  • 2012-05-09
  • 1970-01-01
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-22
  • 1970-01-01
相关资源
最近更新 更多