Javascript 如何申报a“;延期支付”;赋值?
简而言之: 让Javascript 如何申报a“;延期支付”;赋值?,javascript,javascript-events,promise,es6-promise,Javascript,Javascript Events,Promise,Es6 Promise,简而言之: 让a和b成为一些对象,让p成为b的一个属性。此属性可能现在存在,也可能由于某些事件而稍后出现。我正在寻找一种方法,使分配a.p=b.p等待b.p的任务准备就绪 详细信息: 让o成为一个对象: const o = {}; 在我正在处理的实际脚本中,o是一个具有许多属性的自定义对象,但是它们没有引用当前问题,所以让o为空 在同一范围内,将创建一个新的链接元素,以将样式表动态附加到当前文档: const link = document.createElement('link'); Obj
a
和b
成为一些对象,让p
成为b
的一个属性。此属性可能现在存在,也可能由于某些事件而稍后出现。我正在寻找一种方法,使分配a.p=b.p
等待b.p
的任务准备就绪
详细信息:
让o
成为一个对象:
const o = {};
在我正在处理的实际脚本中,o
是一个具有许多属性的自定义对象,但是它们没有引用当前问题,所以让o
为空
在同一范围内,将创建一个新的链接元素,以将样式表动态附加到当前文档:
const link = document.createElement('link');
Object.entries({rel: 'stylesheet', type: 'text/css', href: '/style.css'})
.forEach(([name, value]) => link.setAttribute(name, value));
document.head.appendChild(link);
在此之后,我希望o
具有指向link.sheet
的sheet
属性,例如:
o.sheet = link.sheet; // not working
它不起作用,因为只有在触发link.onload
事件后才创建link.sheet
。我可以为此事件创建处理程序:
link.addEventListener('load', function() {
return this.sheet;
});
但是为了代码的纯度,这个函数不应该有权访问o
,所以我不想在函数体内部编写o.sheet=this.sheet
,或者将o
作为参数传递给它等等。我想创建o.sheet
,并在这个处理程序之外将结果分配给它
所以我想作业应该不是o.sheet=link.sheet
,而是o.sheet=something\u other
,其中something\u other
是我还不知道的。也许是一个承诺,或者特殊的getter,或者什么?你可以用sheet
getter做这样的事情:
Object.defineProperty(o, 'sheet', {
get() {
return link.sheet
}
})
因此,在加载样式表之前,o.sheet
将为null
并在稍后更正对象
这里有一个简单的演示:事实上,承诺是一种有用的解耦机制。在这种情况下,创建链接的代码将返回一个承诺,该承诺将从链接的加载事件处理程序中解析:
function loadSheet() {
return new Promise((resolve, reject) => {
const link = document.createElement('link');
Object.entries({rel: 'stylesheet', type: 'text/css', href: '/style.css'})
.forEach(([name, value]) => link.setAttribute(name, value));
document.head.appendChild(link);
link.addEventListener('load', () => {
resolve(link.sheet);
});
link.addEventListener('error', () => {
reject();
});
});
}
以及使用它的代码:
loadSheet().then(sheet => {
o.sheet = sheet;
// Remainder of the code that needed to wait for `sheet` goes here...
});
包装函数?
var loadSheet = function (cb){
const link = document.createElement('link');
Object.entries({rel: 'stylesheet', type: 'text/css', href: '/style.css'})
.forEach(([name, value]) => link.setAttribute(name, value));
document.head.appendChild(link);
link.addEventListener('load', function() {
cb(sheet);
});
}
// then use like so
loadSheet(function (sheet){
o.sheet = sheet;
});
您可以根据需要将任何额外的参数传递给装载单
可以让这更美好:
- 使用承诺,但可能会增加不必要的复杂性
- 将
(err,sheet)
传递到cb
以允许错误向前传播
- 添加一个
setTimeout
,在工作表加载超时时终止加载,具体取决于需要
解耦与封装
两个对象如何交互有3个选项
A
知道B
B
知道A
做另一件事C
,知道A
和B
如果希望A
和B
100%解耦。然后,制作一个封装a
和B
的函数是唯一的选择。您希望如何得知o.sheet已收到一个值?还是不?@trincot,理想情况下,我希望我的脚本在这里“停止”并“等待”直到链接。样式表
准备就绪,然后将其分配给o.sheet
并进一步移动。您希望脚本执行真的停止吗?对于用户来说,这将是一种糟糕的体验。最好的方法不是停止,而是使用一些回调系统(加上扩展,这可能是一个承诺)。但是,分配发生在回调中,这似乎是您不喜欢的?@trincot,我的脚本需要样式表进一步,因此它必须停止并等待它。@Displayname:@trincot是对的,您不希望脚本引擎停止在那里,因为它会锁定浏览器。您只需要等待工作表进入回调(如果希望耦合,则需要事件回调;如果希望解耦,则需要由事件回调触发的其他内容),因此它将在工作表可用时运行。(Doh!编辑错误:如果在上面第一段之后看到一堆未格式化的代码,请点击刷新。)“…我不想在函数体中写入o.sheet=this.sheet
。”这似乎并没有绕过这一点(除了缺少this
)。@trincot:你已经在那句话的开头省略了重要的一点:“但是为了代码的纯度,这个函数不应该访问o
。”。。。“有了上面的内容,它就没有了。我会尽可能地将“这个属性[它]现在可能存在,或者它以后可能会由于某个事件而出现”本身作为一个承诺。我感到困扰的是,loadSheet
函数有权访问obj
。我希望处理样式表加载的函数只返回结果表
,而不“知道”它将被分配到哪里。@Displayname:这不正是我的答案所显示的吗?不。。!除息的。。。但是有点是的。。。我想不管你怎么做Promise
或cb
您仍然必须将o.sheet
封装到函数中。@PhilPoore:这是针对Displayname的,而不是您,回应了他对上述Decoupling的评论。抱歉造成任何混乱。仅供参考-OP现在澄清了他们的问题(在评论中),此答案不再适用。