模型实例替换为远程方法导致 Angular 调用 Loopback

Model instance replaced with remote method result in Angular call to Loopback

我有一个带有 Angular 前端的 Loopback API,并且在尝试调用非静态远程方法时看到了一些奇怪的行为。

我已经把它归结为这个例子。拨打这样的电话时:

$scope.myInstance = MyModel.findOne({}, function success(value){
  $scope.greeting = value.$prototype$hello({}, function success(){});
});

我发现 $scope.myInstance 最终包含对 $prototype$hello 的调用结果,而 $scope.greeting 是空的。 MyModel 是用这样的远程调用定义的:

module.exports = function(MyModel) {

   MyModel.prototype.hello = function(cb) {
     cb(null,"Hello: " + this.name);
   }

   MyModel.remoteMethod(
     'hello',
     {
       isStatic: false,
       http: { verb: 'get' },
       returns: {arg: 'message', type: 'string'}
     }
   );

};

如果我的模板中有这个:

Greeting = {{ greeting }}, Instance = {{ myInstance }}

我明白了:

Greeting = {}, Instance = {"message":"Hello: Test","$promise":{},"$resolved":true}

用问候语结果清楚地代替了模型实例。我希望在实例变量中看到模型实例:

Greeting = {}, Instance = Instance = {"name":"Test","id":1,"$promise":{},"$resolved":true}

加载过程中模型会短暂闪烁。

我可以通过检索模型的额外一次性实例来解决这个问题,但我希望有人知道为什么会发生这种情况,以及是否有更清洁的解决方案。

2015 年 8 月 12 日更新: 我创建了一个 Plunker 来演示这个问题 here, but this only contains the client-side JS. For the full loopback project, I've added the code to a GitHub repo

有趣的是,Safari 下的行为略有不同,它根本不呈现实例:

Greeting = {}, Instance =

最初描述的行为见于 Chrome。

我检查了你的 plunker,我想我在这里遇到了问题,你的代码是:

$scope.myInstance = MyModel.findOne({}, function success(value){
  $scope.greeting = value.$prototype$hello({}, function success(){});
});

让我们暂时忘记成功函数,findone() 函数 returns 您从 mongodb 请求的文档,正如我认为的那样,这自然意味着返回的文档或查询将存储在 $scope.myInstance 中,这就是您的应用程序的行为方式。 现在对于成功函数,它试图调用响应对象(值)中不存在的 value.$prototype$hello,因此值为 undefined 并且存储在 $scope.greeting 中,这就是为什么它显示为空。

为什么 $prototype$helloundefined 很简单,它是一个原型对象,如果它是您应用程序的一部分,但您正试图通过一个没有它的响应对象访问这个函数.

我希望这能回答你的问题

编辑:

问题出在这一行

 $scope.greeting = value.$prototype$hello({}, function success(){});

就这样制作:

value.$prototype$hello({}, function success(val){$scope.greeting = val.message;},function error(err){console.log(err);});

编辑 2

将你的代码改成这样:

ModelA.findOne({}, function success(value){
  //debugger;
  value.$prototype$hello({}, function success(val){$scope.greeting = val.message;},function error(err){console.log(err);});
}).$promise.then(function(res) {
  $scope.myInstance = res;
});

这样,在解决承诺之前,您的变量中不会有虚假数据。 而且,响应对象具有 $promise 和 $resolved 属性是完全正常的,因为它是一个资源承诺对象

编辑 3

现在在你澄清了你上一条评论的问题后,我能够理解它,我正在寻找其他东西,但无论如何它们是相关的。 发生的是冲突,您正在执行两个异步调用,您应该这样对待它们,代码应该是这样的:

ModelA.findOne({}).$promise.then(function(value) {
  $scope.myInstance = value;
  var v2 = angular.copy(value);
  v2.$prototype$hello({},
    function (val){
      $scope.greeting = val.message;
    },
    function (err){console.log(err);}
  );
});

如果您需要有关代码的更多信息,请告诉我