knockout.js - 简单的 JSON 和 Breeze 导致错误为 "call fetchMetadata first"

标签 knockout.js breeze

我有一个 API 端点,可以输出简单的 JSON,如下所示:

{
  "num_results": 2,
  "objects": [
    {
      "creator": null,
      "id": 1,
      "image": "www.test.com",
      "title": "test",
      "user_id": null
    }
}

我想使用 Breeze 将其放入 Knockout 可观察量中。我认为我需要一个自定义的 jsonResultsAdapter 。我试图遵循埃德蒙兹的例子,但我承认我并没有真正理解它。

var jsonResultsAdapter = new breeze.JsonResultsAdapter({
    name: "test",

    extractResults: function (data) {
        var results = data.results;
        if (!results) throw new Error("Unable to resolve 'results' property");
        return results;
    },

    visitNode: function (node, parseContext, nodeContext) {
        // Make parser
        if (node.objects) {
            return { entityType: "Pin"  }
        }
      }
    });

var dataService = new breeze.DataService( {
        serviceName: "api/",
        hasServerMetadata: false,
        jsonResultsAdapter: jsonResultsAdapter,
});    

var manager = new breeze.EntityManager( {
  dataService: dataService
});

var query = new breeze.EntityQuery.from("pin");

manager.executeQuery(query).then(function(data){
    ko.applyBindings(data);
}).fail(function(e) {
    alert(e);  
});

但是在executeQuery函数内部失败并显示一条消息:

Error: Unable to locate a 'Type' by the name: 'Pin'. Be sure to execute a query or call fetchMetadata first.

我以为我刚刚做到了。我在这里做错了什么?

编辑

  function initialize(metadataStore) {
    var DT = breeze.DataType; // alias

    metadataStore.addEntityType({
        shortName: "Pin",
        namespace: "test",
        dataProperties: {


            creator:    { dataType: DT.String },
            id:         { dataType: DT.Int64, isPartOfKey: true },
            image:      { dataType: DT.String },
            title:      { dataType: DT.String },
            modelLinks: { dataType: DT.Int64 }
        },
    });
  }

已经部分弄清楚了。需要添加一个元数据存储来描述返回的数据类型。但现在我明白了

Error: You cannot apply bindings multiple times to the same element.

最佳答案

我怀疑您的 JsonResultsAdapter 没有执行您认为应该执行的操作。您应该调试它以查看发生了什么。

还要检查返回到查询成功回调的数据。 data.results 中的对象对您来说合适吗?他们有 entityAspect 属性吗? entityType 属性?如果不是,数据就不会成为实体,我认为它们也不会有可观察的属性。

我相信您会将问题追溯到 visitNode 方法。当您在 node.objects 上获得匹配项时,我预测节点本身将如下所示:

{
  "num_results": 2,
  "objects": [
    {
      "creator": null,
      "id": 1,
      "image": "www.test.com",
      "title": "test",
      "user_id": null
    }, 
    ...
  ]
}

您的回应

return { entityType: "Pin"  }

似乎是在告诉 Breeze,这整个事情应该被视为 Pin 类型的数据。

事实显然并非如此。 Pin 数据位于objects 数组内部

您实际上想要匹配这些数据。您可以通过类似的测试来做到这一点

if (node.id && node.title) {
    return { entityType: ...  } // see below
}

或者类似的东西。

风险在于此类测试可能会与 Pin 以外的某些类型的数据匹配。如果您的服务器可以使用数据序列化类型指示器,那么事情就会变得容易得多。

We did this in our rails sample. We added a $type property to each entity object serialized to a Breeze client and set it to the name of the type. That made it easy to identify the node.

您必须返回EntityType而不是类型的名称

看看 "webApi" DataServiceAdapter 的实现.

您将看到没有返回类型的名称。您返回匹配的 EntityType

您需要类似这样的代码:

var type = mappingContext.entityManager.metadataStore.getEntityType('Pin', true);
return { entityType: type  }

我确信您可以想象一种更有效的方法来缓存此类型对象,这样您就不必在每次访问节点时都费力地获取它。

为什么要指定类型的命名空间

您使用命名空间“test”定义了 Pin 类型。为什么?这是服务器上的命名空间吗?还是你刚刚编造出来的?如果你没有的话,你就不需要一个。它只会增加不必要的复杂性。

你可能会侥幸逃脱:

var DT = breeze.DataType; // alias

metadataStore.addEntityType({
    shortName: "Pin",
    dataProperties: {
        creator:    { }, // string is the default
        id:         { dataType: DT.Int64, isPartOfKey: true },
        image:      { },
        title:      { },
        modelLinks: { dataType: DT.Int64 }
    },
});

更好的extractResults函数?

您还可以考虑改进 extractResults 方法,以便它立即消除无关的内容。为什么不像这样直接进入对象级别呢?

extractResults: function (data) {
    var results = data.results && data.results.objects;
    if (!results) throw new Error("Unable to resolve 'results.objects' property");
    return results;
} 

关于knockout.js - 简单的 JSON 和 Breeze 导致错误为 "call fetchMetadata first",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28569338/

相关文章:

javascript - 从两个可观察数组中获取计算值

javascript - 在页面顶部显示标题 - 滚动事件重新触发问题

breeze - 如何 "dispose"一个 EntityManager

laravel-8 : Why i cannot install Laravel/Breeze

css - knockout css 数据绑定(bind)不应用类

javascript - 将 Javascript onkeypress 转换为 knockoutjs 以在输入时调用

javascript - 显示数据,在 knockout 中一次显示一个对象元素

entity-framework-5 - 带有存储库的 Breeze

BreezeJS 和执行 Entity Framework 存储过程

javascript - 如何使用 breezejs 保护添加或删除实体