【问题标题】:Simple JSON and Breeze resulting in error to "call fetchMetadata first"简单的 JSON 和 Breeze 导致“首先调用 fetchMetadata”的错误
【发布时间】:2015-04-18 14:40:32
【问题描述】:

我有一个 API 端点,它可以像这样输出简单的 JSON:

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

我想使用 Breeze 将其放入 Knockout observables。我收集到我需要一个自定义的jsonResultsAdapter。我试图跟随 Edmunds 的例子,但我承认我真的不明白。

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 函数内部失败并显示一条消息:

错误:无法通过名称找到“类型”:“Pin”。请务必先执行查询或调用 fetchMetadata。

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

编辑

  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 }
        },
    });
  }

部分弄明白了。需要添加一个 metadataStore 来描述返回的数据类型。但现在我明白了

错误:您不能对同一个元素多次应用绑定。

【问题讨论】:

  • 你的最后一个错误与Breeze无关,是Knockout.js的问题。
  • 我意识到这一点,但我怀疑它与微风如何从导致问题的 JSON 创建对象有关。我开始相信微风不会给你带来任何东西,除非你有一个 odata 端点。这肯定不会让我在创建个人 ko 可观察对象时节省 LOC。实际上可能更多。

标签: knockout.js breeze


【解决方案1】:

我怀疑您的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 以外的某些类型的数据。如果您的服务器可以用数据序列化类型指示符,这将变得非常容易。

我们在our rails sample 中进行了此操作。我们added a $type property 将每个实体对象序列化到 Breeze 客户端并将其设置为类型的名称。这使得识别节点变得容易。

您必须返回 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 方法,以便它立即摆脱无关的东西。为什么不直接像这样直接进入objects 级别?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 2020-12-03
    • 2018-12-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    相关资源
    最近更新 更多