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现在澄清了他们的问题(在评论中),此答案不再适用。