Asynchronous Aurelia-将repeat.for绑定到从服务器调用填充的计算数组

Asynchronous Aurelia-将repeat.for绑定到从服务器调用填充的计算数组,asynchronous,binding,ecmascript-6,httpclient,aurelia,Asynchronous,Binding,Ecmascript 6,Httpclient,Aurelia,正如标题所示,我试图将一个元素源绑定到一个计算数组,该数组由http.fetch调用的结果填充。下面是代码(这个问题的有趣部分): 观点: <tr> <td repeat.for="boardItemFilter of boardItemFilters"> <input if.bind="boardItemFilter.isStringFilter()" type="text" value.bind="boardItemFilter.Valu

正如标题所示,我试图将一个元素源绑定到一个计算数组,该数组由http.fetch调用的结果填充。下面是代码(这个问题的有趣部分):

观点:

<tr>
    <td repeat.for="boardItemFilter of boardItemFilters">
        <input if.bind="boardItemFilter.isStringFilter()" type="text" value.bind="boardItemFilter.Value & debounce:400" />
        <div if.bind="boardItemFilter.isCheckboxFilter()" repeat.for="sourceValue of boardItemFilter.SourceValues">
            <input type="checkbox" value.bind="sourceValue" checked.bind="boardItemFilter.SelectedValues" />
            <span textcontent.bind="sourceValue"></span>
        </div>
    </td>
</tr>
其中fetchBoardItemFiltersByUnit()函数为:

fetchBoardItemFiltersByUnit(unitName){
    let self = this;
    let request = {'unitName': unitName};
    return this.http.fetch('BoardFilters',{
        method: 'post',
        body: json(request),
    }).then(response => response.json())
      .then(response => this.ExtendFilters(response));
}
所选设备上的
boardItemFilters()
计算触发器将正确更改。datacontext调用完成后,该部分工作正常。当aurelia在http.fetch完成之前尝试绑定属性时,就会出现问题。然后,它认为该属性不可重复,并中断。在这些错误之后,
console.log(result)
显示服务器返回的预期对象数组,但结果未分配给computed属性。我尝试使用信号行为手动重新触发绑定,但没有成功

问题自然是,我做错了什么?结果是否未存储到computed属性中,或者正在以不期望的方式绑定它?这个问题的正确解决方案是什么

我已经尝试了很多方法,唯一有效的方法是创建一个局部变量来存储http结果,并且总是在promise函数之外返回该变量。但很自然,它将始终返回前一个状态,因为它将运行异步调用,并在调用完成之前返回局部变量。这当然是不能接受的

还是说Aurelia还不支持异步绑定

提前谢谢你

编辑:
我已经设法破解了一个解决方案,但它非常难看(使用promise函数中的bindingSignaler重新绑定,使用newValue和oldValue比较来避免无限计算调用等)。我仍然很想听到实现这一目标的正确方法

这里有一种方法可以解决这种不依赖异步绑定的冗长计算操作:

  • 将从属属性从计算属性更改为常规属性
  • 手动观察依赖项以调用冗长的操作。仅当冗长的操作完成时,才更新从属属性
例如:

export class App {
  @bindable count;

  constructor() {
    this.count = 3;
    this.computeNums(this.count)
      .then(result => this.nums = result);
  }

  countChanged(value) {
    this.computeNums(value)
      .then(result => this.nums = result);
  }

  computeNums(count) {
    let result = [];
    for (let i = 1; i <= count; i++) {
      result.push(i);
    }

    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(result), 1000);
    });
  }
}
导出类应用程序{
@可绑定计数;
构造函数(){
这个.计数=3;
这个.计算机(这个.计数)
。然后(result=>this.nums=result);
}
计数已更改(值){
这个。计算(值)
。然后(result=>this.nums=result);
}
计算机(计数){
让结果=[];
for(设i=1;i{
setTimeout(()=>解析(结果),1000);
});
}
}
这里,
nums
是根据
count
计算的<代码>计算机模拟冗长的操作

观察
计数
是通过组合
@bindable
countChanged
实现的。您可能希望改用绑定引擎API,如下所示


可以运行的完整示例:

您正在尝试在重复的
的每次迭代中进行http调用。for
,在我看来,这绝对不是一个好方法。你应该重写整个算法。此外,要绑定计算属性,不必使用括号,这
if.bind=“boardItemFilter.isStringFilter”
是否足够?我的印象是,我将填充数组一次,然后用repeat.for.对其进行迭代。。你能解释一下吗?编辑:我刚刚查看了网络流量,api只被调用一次,而不是每次迭代..哦,isStringFilter()是一个函数,我用它扩展了filter对象,所以需要括号。。不过,我可以将其转换为计算属性,这样更有意义。谢谢:)对不起!!!我把
boardItemFilters
isStringFilter()
搞得一团糟。他们非常相似,我认为他们是一样的lol。我会再看一遍这个问题,然后我可以分享我的观点。也许这就是你要找的。它仍然是实验性的。不过,我会通过改变逻辑结构而不是依赖某种异步绑定来解决这个问题。谢谢,这对这个案子很有效。
export class App {
  @bindable count;

  constructor() {
    this.count = 3;
    this.computeNums(this.count)
      .then(result => this.nums = result);
  }

  countChanged(value) {
    this.computeNums(value)
      .then(result => this.nums = result);
  }

  computeNums(count) {
    let result = [];
    for (let i = 1; i <= count; i++) {
      result.push(i);
    }

    return new Promise((resolve, reject) => {
      setTimeout(() => resolve(result), 1000);
    });
  }
}