【问题标题】:Angular async promise is not chaining correctly to give back 1st call in order to make 2nd callAngular 异步承诺未正确链接以返回第一次调用以进行第二次调用
【发布时间】:2017-03-11 02:21:41
【问题描述】:

我想在调用第二个服务之前返回一个邮政编码,这样——据我所知——我可以封装一个promise,然后稍后再请求promise。所以我想我会把我的第二个服务放在第一个服务的承诺中。但是以这种方式链接承诺并不友好。

Angular 工厂在工厂方法内部被调用:

var userGeoPromise = userService.getGeoposition().then(function (geoposition) {
    vm.geoposition = geoposition;
            return addressService.reverseGeocode(geoposition.coords);
    }).then(function (data) {
            vm.currentLocation = googleService.googleAddressComponentsToAddress(data.results[0]);
            zipCodeCurrent = vm.currentLocation.zip;
    });

注意以上两点:

  1. 我将承诺分配给var userGeoPromise
  2. zipCodeCurrent 设置为包含邮政编码

Promise 测试工作正常:

userGeoPromise.then( function() {
      console.log('should always show', zipCodeCurrent);
});

第二次服务电话:

userGeoPromise.then( function() {
     var serviceBase = "http://localhost:2295/api/getservicezip/"+ zipCodeCurrent;
     var serviceZipPromise = $http.get(serviceBase);
     return serviceZipPromise.then(function (results) {
          console.log('serviceZipPromise', results);
          return results.data;
     });
});

但是当我把serviceZipPromise.then... 放在另一个承诺中时,网站模式只是旋转

【问题讨论】:

  • 我认为googleService.googleAddressComponentsToAddress不是异步的
  • 控制台消息中有什么要说的吗?可能是 $http.get(serviceBase) 正在拒绝(您绝对没有拒绝处理程序,因此有理由认为最后一段代码中有某些内容正在拒绝)
  • 好吧,我不确定这个 googleservice 的事情......但似乎只要我在调用其他服务之前等待这件事,就没有关系了。早些时候我什至尝试调用一个函数并将第二个服务包装在一个函数中,认为它会很好,因为它最终会被调用,但这也不起作用。
  • 我可以将第二个服务调用从 promise 调用中提取出来,并且它可以工作,除了我必须硬编码邮政编码 return serviceZipPromise.then(...
  • 我在互联网上找不到任何关于 googleAddressComponentsToAddress 的信息 - 这是你自己的功能吗?

标签: javascript angularjs asynchronous promise angular-promise


【解决方案1】:

then 回调中,您应该返回结果值,而不是将其分配给zipCodeCurrent(或任何其他变量)。您在第一个 then 回调中正确执行了此操作,但您应该在第二个中应用相同的原则:

var userGeoPromise = userService.getGeoposition().then(function (geoposition) {
    vm.geoposition = geoposition;
    return addressService.reverseGeocode(geoposition.coords);
}).then(function (data) {
    vm.currentLocation = googleService.googleAddressComponentsToAddress(data.results[0]);
    return vm.currentLocation.zip; // *** return it
});

注意:我没有触及对 vm 属性的赋值,但通常你应该避免改变(显然)存在于这些回调函数范围之外的变量。

Promise 测试如下所示:

userGeoPromise.then( function(zipCodeCurrent) { // *** add the argument
    console.log('should always show', zipCodeCurrent);
});

第二个nd 服务有一个嵌套的then 调用,这是要避免的。不要在嵌套的中间承诺上调用then,而是返回该承诺,然后在主承诺链上应用then

userGeoPromise.then( function(zipCodeCurrent) { // *** add the argument as in the test
    var serviceBase = "http://localhost:2295/api/getservicezip/"+ zipCodeCurrent;
    return $http.get(serviceBase); // *** return the promise
}).then( function (results) { // *** move the then-callback to the outer chain
    console.log('serviceZipPromise', results);
    return results.data;
}).catch( function (error) { // *** add error handling at the end of the chain
    console.log('error occurred:', error);
});

请注意嵌套级别如何永远不会超过 1。

【讨论】:

    【解决方案2】:

    切换顺序并添加 2 个单独的错误处理程序(顺便说一句,这是一个很好的做法)

      var serviceZipPromise = $http.get(serviceBase);  // call up 
            return serviceZipPromise.then(function (results) {
                console.log('should always show', zipCodeCurrent);
                userGeoPromise.then(function () {
                    //console.log('serviceZipPromise', results);
                    console.log('inside servicezip ', zipCodeCurrent);
    
                }, function (err) {  // error from userGeoPromise
                    console.log(err);
                });
    
                 return results.data;  // THIS will return the data
            }, function (err) { // outer error,  this was switched 
                console.log(err);
    
            });
    

    这应该不会出错,但要让您真正的serviceBase 最终使用邮政编码,您可能需要稍后执行它

    为您更新答案

      // created part of the api call
      var xserviceBase = "http://localhost:2295";  // this looks to be your base
    
      return userGeoPromise.then(function(){
           return $http.get(xserviceBase + '/api/getserviceablezip/' + zipCodeCurrent).then(function(results){
                 return results.data;
           })
      });
    

    是的,我知道 3 个返回看起来有点讨厌,但它应该可以工作

    【讨论】:

    • 嗯,总的来说我喜欢它,没有错误,但问题仍然是 serviceBase 需要在里面,因为它也需要传递邮政编码
    • 对,我想,好的,我会显示一个更新的答案,它已经很晚了,所以我不打算进行所有错误处理,但我更新的答案应该“有效”要通过的 zip。
    猜你喜欢
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多