2016-03-08 124 views
0

我正在開發一個實用程序服務,用於處理角度中的SharePoint項目。我正在更新我的代碼以對異步使用角度承諾。而不是回調函數,所以請原諒我的代碼在轉換過程中有點混亂。我已經寫了一些代碼來更新單個列表項目,然後我重複使用該函數來批量更新多個項目。該代碼正在工作,http請求正在改變我的列表中的項目,但我似乎無法獲得在更新多個項目時回到頂端的承諾。這裏是我的代碼:

this.UpdateListItem = function (webUrl, listName, itemId, itemProperties, success, failure) { 
    if (typeof lists[listName] === 'undefined') { 
     lists[listName] = []; 
    } 
    var deferred = $q.defer(); 

    var post = angular.copy(itemProperties); 
    DataUtilitySvc.ConvertDatesJson(post); 
    this.GetListItemById(webUrl, listName, itemId) 
     .then(function (item) { 
      $http({ 
       url: item.__metadata.uri, 
       method: 'POST', 
       contentType: 'application/json', 
       processData: false, 
       headers: { 
        "Accept": "application/json;odata=verbose", 
        "X-HTTP-Method": "MERGE", 
        "If-Match": item.__metadata.etag 
       }, 
       data: JSON.stringify(post), 
       dataType: "json", 
      }).then(function SuccessCB(response) { 
       var temp = []; 
       temp.push(itemProperties); 
       DataUtilitySvc.MergeByProperty(lists[listName], temp, 'Id'); 
       deferred.resolve(response); 
      }, function FailureCB(response) { 
       this.GetListItems(webUrl, listName); 
       deferred.reject(response); 
      }); 
     }, function (error) { 
      deferred.reject(error); 
     }); 
    return deferred.promise; 
}; 


this.UpdateListItems = function (webUrl, listName, itemsJson, success, failure) { 
    if (numItems == -1) { 
     numItems = itemsJson.length; 
     c = 0; 
     f = 0; 
    } 
    var promises = []; 

    itemsJson.forEach(function (itemProps) { 
     var deferred = $q.defer(); 
     this.UpdateListItem(webUrl, listName, itemProps.Id, itemProps) 
      .then(function() { 
       c++; 
       if (c == numItems && f == 0) { 
        numItems = -1; 
        deferred.resolve(itemsJson[listName]); 
       } 
      }, function (error) { 
       c++; f++; 
       if (c == numItems) { 
        numItems = -1; 
        deferred.reject(error); 
       } 
      }); 
     promises.push(deferred.promise); 
    }, this); 
    return $q.all(promises); 
}; 

然後這裏是我從哪裏調用角度控制器的服務功能。 animateAlert調用會使引導警報出現,然後用指定的文本消失。

$scope.UpdateListItem = function (webUrl, listName, itemId, itemProperties, success, failure) { 
    SPListUtility.UpdateListItem(webUrl, listName, itemId, itemProperties, success, failure) 

     // The following then clause works and the animations show as intended 

     .then(function success(data) { 
      console.log(JSON.stringify(data)); 
      $scope.animateAlert("myAlert", "alertText", "Operation Successful!", "success"); 
     }, function failure(error) { 
      console.log("Error " + error.status + ": " + error.statusText); 
      $scope.animateAlert("myAlert", "alertText", "Error " + error.status + ": " + error.statusText, "danger"); 
     }); 
}; 

$scope.UpdateListItems = function (webUrl, listName, itemsJson, success, failure) { 
    SPListUtility.UpdateListItems(webUrl, listName, itemsJson, success, failure) 

     // The following section is what never seems to get called. These animations never show up 

     .then(function success() { 
      $scope.animateAlert("myAlert", "alertText", "Items Saved", "success"); 
     }, function failure(error) { 
      console.log("Error " + error.status + ": " + error.statusText); 
      $scope.animateAlert("myAlert", "alertText", "Error " + error.status + ": " + error.statusText, "danger"); 
     }); 
}; 
+0

只有在'(c == numItems && f == 0)'爲真時,您的承諾纔會被解決。否則,他們永遠不會解決也不會被拒絕。 –

+0

避免[deferred antipattern](http://stackoverflow.com/q/23803743/1048572)!你可以通過[簡單地''將它們從'then'回調](http://stackoverflow.com/a/22562045/1048572)返回到頂端「來回報頂部。 – Bergi

+0

嗨@Bergi,你能否改變我的一些代碼來證明你的意思。我閱讀了您發佈的文章,但我無法弄清楚如何將其應用於我的情況。謝謝。 –

回答

0

我覺得@Bergi是在暗示我這樣做如下:

this.GetListItemById = function (webUrl, listName, itemId, loading) { 
    var url = webUrl + "/_vti_bin/listdata.svc/" + listName + "(" + itemId + ")"; 
    return $http({ 
     url: url, 
     method: 'GET', 
     processData: false, 
     headers: { "Accept": "application/json;odata=verbose" }, 
    }).success(function (data) { 
     console.log("This Executes"); 
     return data.d; 
    }).error(function (response) { 
     return response; 
    }); 
}; 

這似乎有種做我想做的。它執行異步調用,但它始終會返回整個成功/然後包含數據,狀態,標題,配置和statusText的對象。即使我具體說返回data.d它仍然返回整個對象。任何人都知道我錯過了什麼?

+0

這是[預計](https://stackoverflow.com/questions/35415659/angularjs-then-behaves-differently-than-success-error) - 使用'然後'/'catch'而不是'成功'/ 'error'(或者在這裏不要使用'catch',因爲你沒有對錯誤做任何事情) – Bergi

0

感謝@Bergi的回覆。如果請求失敗,我想將響應返回給用戶。這是在我的控制器代碼:

$scope.GetListItemById = function (webUrl, listName, itemId) { 
    SPListUtility.GetListItemById(webUrl, listName, itemId) 
     .then(function success(data) { 
      console.log(JSON.stringify(data)); 
      $scope.animateAlert("myAlert", "alertText", "Item: " + data.Title + " loaded", "success"); 
     }).catch(function failure(error) { 
      console.log("Error " + error.status + ": " + error.statusText); 
      $scope.animateAlert("myAlert", "alertText", "Error " + error.status + ": " + error.statusText, "danger"); 
     }); 
}; 

這一切主要是現在的實驗和測試,但我想這個服務是未來強勁。那麼似乎工作的項目存在,但問題是,如果我試圖檢索一個不存在的項目,它會拋出一個404上面列出的then函數仍然被調用,當它返回而不是像我打算的趕上。通過手動返回和Promise.reject,我可以通過更改服務函數來強制它工作,但是遵循以下最佳實踐?

this.GetListItemById = function (webUrl, listName, itemId, loading) { 
    var url = webUrl + "/_vti_bin/listdata.svc/" + listName + "(" + itemId + ")"; 
    //var deferred = $q.defer(); 
    return $http({ 
     url: url, 
     method: 'GET', 
     processData: false, 
     headers: { "Accept": "application/json;odata=verbose" }, 
    }).then(function SuccessCB(response) { 
     //console.log(JSON.stringify(response)); 
     return response.data.d; 
    }, function FailureCB(response) { 
     return Promise.reject(response); 
    }); 
    //return deferred.promise; 
};