2016-02-04 62 views
0

当我这样定义AngularJS工厂返回“未定义”

dataFactory.all = function() { 
    return 'test01'; 
} 

工厂方法并调用它在控制器这样

console.log(Data.all()); 

我可以得到test01打印。然而,当我在工厂添加一些逻辑all()方法这样

dataFactory.all = function() { 

    $http 
     .get('/api/hey') 
     .success(function(data) { 

     $http 
      .get('/api/hi') 
      .success(function(data) { 

      return 'test'; // 'test' can not be printed, and console show 'undefined' 
      }); 
     }); 
    //return 'test01'; //can be printed; 
    }; 

那么“测试”不能经由控制器打印。因为我在回调中放入return声明?

请让我知道我在做什么错了?

谢谢。

回答

1

看看角的$qdocs)。使用$ q,您可以创建一个延迟对象并从您的工厂方法返回它的承诺。

这应该允许您从您的$ HTTP调用检索得到的数据在一个then回调,因为你的工厂将回到一个承诺:

dataFactory.all = function() { 
    // create deferred object 
    var deferred = $q.defer(); 

    $http.get('/api/hey') 
    .success(function(data) { 

    $http.get('/api/hi') 
    .success(function(data) { 

     // resolve the promise with your http request result, this value will 
     // be the result passed to your factory method's 
     // `then` callback 
     deferred.resolve(data); 
    } 
    } 

    return deferred.promise; 
} 

更新

@HankScorpio是正确的,这可以通过返回$http.get函数调用大大简化,因为它们自己返回承诺:

dataFactory.all = function() { 
    return $http.get('/api/hey').success(function(response) { 
    return $http.get('/api/hi'); 
    }); 
} 

工作更新是在这里:http://plnkr.co/edit/wtMnOjjUnKV5x8CQrbIm?p=preview

+0

谢谢@pultrone – leonsPAPA

+1

没有必要使用'$ q.defer()' 只需返回'$ http.get()'的结果使用$ http.get()的地方)足以让这个函数起作用。 $ q应该将承诺链接在一起。 – HankScorpio

+0

是的,有你,我认为@ HankScorpio – leonsPAPA

1

是的,正如你指出的那样,你把回调函数的返回。 all()函数没有返回语句,默认情况下所有函数都会返回undefined

您遇到的问题是,您现在正在处理将在未来的未知时间返回数据的异步函数(与同步函数相反,该函数立即返回数据以供下一行使用的代码)。

在这种情况下,你使用$ HTTP方法以及$http.get()会返回一个承诺。 https://docs.angularjs.org/api/ng/service/ $ q

查看$ http文档中的示例。具体来说,看看他们与then()功能做什么:https://docs.angularjs.org/api/ng/service/ $ HTTP

+0

非常感谢@ HankScorpio – leonsPAPA

1

我不认为它的,因为你已经正确地建造它,但它看起来好像贵厂($http)方法是异步运行。请尝试返回一个承诺,像这样:

datafactory.all = function() { 

    return new Promise(resolve, reject){ 
     // Your logic here... 

    $http 
     .get('/api/hey') 
     .success(function(data) { 
      resolve(data); 
     }) 
     .fail(function(err){ 
      reject(err); 
     }); 
    } 

}; 

然后你就可以消耗你的工厂方法,像这样:

datafactory.all().then(function(result){ 
    // Success! 
}, function(err){ 
    // Error! 
}); 
+0

谢谢@MatthewMerryfull – leonsPAPA

1

因为你没有返回在all方法的范围内的任何值,你也需要注意的是$http返回promise

所以..你的方法可以somemething这样的:

dataFactory.all = function(jobname) { 
    return $http.get('/api/jobs/' + jobname + '/realtimeData').success(function(realtime) { 
    return $http.get('/api/jobs/' + jobname + '/nonliveData').success(function(nonlive) { 
     return 'test'; 
    }); 
    }); 
}; 

或..作废嵌套的承诺,你可以使用Flattened Promise Chains重构了一下你的代码:

dataFactory.all = function(jobname) { 
    return $http.get('/api/jobs/' + jobname + '/realtimeData').then(function(realtime) { 
    // do something with realtime 
    return $http.get('/api/jobs/' + jobname + '/nonliveData'); 
    }).then(function(nonlive){ 
    return 'test'; 
    }); 
}; 

而且因为你的方法all现在退货承诺,您需要:

dataFactory.all(jobname).then(function(nonlive){ 
    console.log(nonlive); // should return test! 
}); 
+0

是的,你也是对的,它帮助了很多。但我首先看到另一个答案,所以我只能给你一个投票,非常感谢@ manzapanza – leonsPAPA