Loopback - getting function back instead of values

百般思念 提交于 2019-12-24 02:30:38

问题


For some endpoints I get a function back when called instead of the actual values (code at the end). It looks like that it only appears for nested endpoints through my Patient model.

E.g. localhost:3000/api/Patients/{id}/MeasDescPatRels

However this works fine: localhost:3000/api/Patients/{id}/MeasuredDataPoints

In my webapp it is not really a problem, apparently the returned function is just called by JS and gives me the correct data. However I have an android app calling the exact same endpoints.

EDIT: I'm also not sure when exactly this behaviour starts. Sometimes right after creating a patient model but sometimes it works for hours, even days.

Returned function:

function (condOrRefresh, options, cb) {
    if (arguments.length === 0) {
      if (typeof f.value === 'function') {
        return f.value(self);
      } else if (self.__cachedRelations) {
        return self.__cachedRelations[name];
      }
    } else {
      if (typeof condOrRefresh === 'function' &&
          options === undefined && cb === undefined) {
        // customer.orders(cb)
        cb = condOrRefresh;
        options = {};
        condOrRefresh = undefined;
      } else if (typeof options === 'function' && cb === undefined) {
        // customer.orders(condOrRefresh, cb);
        cb = options;
        options = {};
      }
      options = options || {};
      // Check if there is a through model
      // see https://github.com/strongloop/loopback/issues/1076
      if (f._scope.collect &&
        condOrRefresh !== null && typeof condOrRefresh === 'object') {
        //extract the paging filters to the through model
        ['limit', 'offset', 'skip', 'order'].forEach(function(pagerFilter) {
          if (typeof(condOrRefresh[pagerFilter]) !== 'undefined') {
            f._scope[pagerFilter] = condOrRefresh[pagerFilter];
            delete condOrRefresh[pagerFilter];
          }
        });
        // Adjust the include so that the condition will be applied to
        // the target model
        f._scope.include = {
          relation: f._scope.collect,
          scope: condOrRefresh,
        };
        condOrRefresh = {};
      }
      return definition.related(self, f._scope, condOrRefresh, options, cb);
    }
  }

MeasDescPatRels model (not working):

{
    "name": "MeasDescPatRel",
    "base": "PersistedModel",
    "strict": false,
    "idInjection": false,
    "options": {
      "validateUpsert": true
    },
    "properties": {
      "reminderData": {
        "type": "object"
      },
      "alarmData": {
        "type": "object"
      }
    },
    "validations": [],
    "relations": {
      "patient": {
        "type": "belongsTo",
        "model": "Patient",
        "foreignKey": "patientId"
      },
      "measurementDescription": {
        "type": "belongsTo",
        "model": "MeasurementDescription",
        "foreignKey": ""
      }
    },
    "acls": [
      {
        "accessType": "*",
        "principalType": "ROLE",
        "principalId": "$everyone",
        "permission": "ALLOW"
      },
      {
        "accessType": "WRITE",
        "principalType": "ROLE",
        "principalId": "$everyone",
        "permission": "ALLOW"
      }
    ],
    "methods": {}
  }

HomeGateway model (not working):

{
  "name": "HomeGateWay",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "model": {
      "type": "string",
      "required": true
    },
    "version": {
      "type": "string",
      "required": true
    },
    "onlineStatus": {
      "type": "boolean",
      "required": true
    },
    "macAdress": {
      "type": "string",
      "id": true,
      "required": true
    }
  },
  "validations": [],
  "relations": {
    "patient": {
      "type": "belongsTo",
      "model": "Patient",
      "foreignKey": ""
    }
  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW"
    }
  ],
  "methods": {}
}

MeasuredDataPoint model (working):

    {
  "name": "MeasuredDataPoint",
  "base": "PersistedModel",
  "strict": false,
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "created": {
      "type": "date",
      "required": false
    },
    "timestamp": {
      "type": "date",
      "required": false
    },
    "lastUpdated": {
      "type": "date",
      "required": false
    }
  },
  "validations": [],
  "relations": {
    "measurementDescription": {
      "type": "belongsTo",
      "model": "MeasurementDescription",
      "foreignKey": ""
    },
    "patient": {
      "type": "belongsTo",
      "model": "Patient",
      "foreignKey": "patientId"
    }
  },
  "acls": [
    {
      "accessType": "*",
      "principalType": "ROLE",
      "principalId": "$everyone",
      "permission": "ALLOW"
    }
  ],
  "methods": {}
}

回答1:


I reproduced this error:

SomeModel.find({ where: { userId: userId }, include : ['otherModel'] }, (err, response) => {
    var someArray = response;
    for (var x in someArray) {
      var otherModel = someArray[x].otherModel;
      console.log(otherModel);
    }
 });

The console output of otherModel is :

function (condOrRefresh, options, cb) {
        if (arguments.length === 0) {
          if (typeof f.value === 'function') {
            return f.value(self);
          } else if (self.__cachedRelations) {
            return self.__cachedRelations[name];
          }
        } else {
          const condOrRefreshIsCallBack = typeof condOrRefresh === 'function' &&
            options === undefined &&
            cb === undefined;
          if (condOrRefreshIsCallBack) {
            // customer.orders(cb)
            cb = condOrRefresh;
            options = {};
            condOrRefresh = undefined;
          } else if (typeof options === 'function' && cb === undefined) {
            // customer.orders(condOrRefresh, cb);
            cb = options;
            options = {};
          }
          options = options || {};
          // Check if there is a through model
          // see https://github.com/strongloop/loopback/issues/1076
          if (f._scope.collect &&
            condOrRefresh !== null && typeof condOrRefresh === 'object') {
            f._scope.include = {
              relation: f._scope.collect,
              scope: condOrRefresh,
            };
            condOrRefresh = {};
          }
          return definition.related(self, f._scope, condOrRefresh, options, cb);
        }
      }

Since the output of otherModel is a function. I tried calling it with : var otherModel = batchArray[x].otherModel() as a function instead of var otherModel = batchArray[x].otherModel. It gives the desired output.

This behaviour explains that the include filter returns a function of the model which gets executed and passes as an object to the frontend but in the backend it needs to be called as a function.

I am still trying to figure out how it returns the desired object to frontend and a function to backend. Any leads would be helpful.



来源:https://stackoverflow.com/questions/43609499/loopback-getting-function-back-instead-of-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!