2016-08-08 3 views
2

일부 루프 내에서 루프 및 중첩 기능을 사용하여 약속을 사용하려고합니다. REST 호출에서 SharePoint 목록 항목을 가져 오는 일련의 함수가 있습니다. 일단 실행이 완료되면 다시 가져온 데이터를 사용하는 다른 함수가 호출됩니다.루프 및 중첩 된 기능으로 약속 사용

여러 개의 목록이 있고 각각에 여러 개의 목록 항목이 있기 때문에 각 REST 호출을 만들기 위해 while 루프를 사용했으며 거기에서 데이터 (목록 항목)가 개체에 넣어집니다. 이러한 객체는 배열에 배치되고 그 두 번째 함수는 계속 사용됩니다.

약속의 응답을받는 데 문제가 있습니다. 배열에 푸시 된 여러 약속을 가지고 생각한 다음 Promise.all을 사용하여 then을 사용하기 전에 모든 것이 해결되었는지 확인하십시오. 문제는 내가 resolve을 올바로 반환하지 않기 때문에 모든 약속이 pending 인 채 유지된다는 것입니다. 아래를 봐주세요.

function onQuerySuccess(sender, args) { 
     var itemEnumerator = items.getEnumerator(); 

     while (itemEnumerator.moveNext()) { 
      var promise = new Promise(function (resolve, reject) { 
       var item = itemEnumerator.get_current(); 
       item = item.get_item('URL'); 
       var itemUrl = item.get_description(); 

       getRequestItemsFromList(itemUrl); 
      }); 

      promises.push(promise); // all promises are present, but their status is pending 
     } 

     console.log(promises); 

     Promise.all(promises).then(function (val) { 
      console.log(val); 
      execFuncs(); // function to execute once all the above are done 
     }).catch(function (response) { 
      console.log(response); 
     }); 
    } 

이 포함 된 기능의 많은, 그래서이 실행 순서이기 때문에 : 나는 그 줄의 끝 이후 나는 Promise.resolve() 전화 낸 곳

getRequestItemsFromList //gets url for each list 
execCrossDomainRequest (on success call) // makes REST call to get list and its items 
cleanData // trims data and puts it in objects 

마지막입니다.

어느 쪽이든 작동하지 않습니다. 다른 스레드를 체크 아웃했지만 라이브러리를 사용하지 않고이 작업을 수행하려고합니다. 미리 감사드립니다.

편집 :

전체 관련 코드 :

var promises = []; 

window.requests = []; 

function getRequestLists() { 
    var requestsLists = hostWeb.get_lists().getByTitle('Name'); // sharepoint list with all the request list urls. 
    context.load(requestsLists); 

    var camlQuery = new SP.CamlQuery(); 
    camlQuery.set_viewXml('<View></View>'); 
    var items = requestsLists.getItems(camlQuery); 

    context.load(items, 'Include(URL)'); 

    context.executeQueryAsync(onQuerySuccess, onQueryFail); 

    function onQuerySuccess(sender, args) { 
     var itemEnumerator = items.getEnumerator(); 

     while (itemEnumerator.moveNext()) { 
      var promise = new Promise(function (resolve, reject) { 
       var item = itemEnumerator.get_current(); 
       item = item.get_item('URL'); 
       var itemUrl = item.get_description(); 

       getRequestItemsFromList(itemUrl); 
      }); 

      promises.push(promise); 
     } 

     console.log(promises); 

     Promise.all(promises).then(function (val) { 
      console.log(val); 
      execFuncs(); // not shown here 
     }).catch(function (response) { 
      console.log(response); 
     }); 
    } 

    function onQueryFail(sender, args) { 
     alert("Request to retrieve list URL items has failed. " + args.get_message()); 
    } 
} 

function getRequestItemsFromList(url) { 
    var lastPos = getSubstringIndex(url, "/", 4); 
    var webUrl = url.substring(0, lastPos); // truncates list url to parse out web url  

    var absListPos = getSubstringIndex(url, "AllItems.aspx", 1); 
    var absListUrl = url.substring(0, absListPos); // truncates the AllItems.aspx at the end of the list url 

    var relListPos = getSubstringIndex(absListUrl, "/", 3); 
    var relListUrl = absListUrl.substring(relListPos, absListUrl.length); // gets the list's relative url 

    var listName = "List Name"; 

    console.log(webUrl); 
    execCrossDomainRequest(webUrl, listName, absListUrl); 
} 

function execCrossDomainRequest(webUrl, listName, absListUrl) { 
    var executor = new SP.RequestExecutor(appWebUrl); 

    executor.executeAsync({ // to collect the list description 
     url: appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle(@name)?" + 
      "@target='" + webUrl + "'&@name='" + listName + "'" + 
      "&$select=Description", 
     method: "GET", 
     headers: { "Accept": "application/json; odata=verbose" }, 
     success: onCallSuccess, 
     error: onCallFail 
    }); 

    function onCallSuccess(data) { 
     var json = JSON.parse(data.body); 
     var description = json.d.Description; 

     executor.executeAsync({ // to collect the list item information 
      url: appWebUrl + "/_api/SP.AppContextSite(@target)/web/lists/getbytitle(@name)/items?" + 
       "@target='" + webUrl + "'&@name='" + listName + "'" + 
       "&$top=500&$select=*," + 
       "Assigned_x0020_To/Title" + 
       "&$expand=Assigned_x0020_To/Id", 
      method: "GET", 
      headers: { "Accept": "application/json; odata=verbose" }, 
      success: onItemsCallSuccess, 
      error: onItemsCallFail 
     }); 

     function onItemsCallSuccess(data) { 
      var itemsJson = JSON.parse(data.body); 
      var results = itemsJson.d.results; 

      cleanData(results, description, absListUrl); 
     } 

     function onItemsCallFail(data, errorCode, errorMessage) { 
      console.log("Could not make list items cross domain call. " + errorMessage); 
     } 
    } 

    function onCallFail(data, errorCode, errorMessage) { 
     console.log("Could not make list cross domain call. " + errorMessage); 
    } 
} 

function cleanData(results, listDescription, absListUrl) { 

    if (!results.length) { 
     return; 
    } 

    for (var i = 0; i < results.length; i++) { 
     var client = listDescription; 
     var id = results[i].ID; 
     ... 

     } 

     var request = new Request(client, id, path, title, status, estimated, assignedTo, priority, description, response); 

     window.requests.push(request); 
    } 

    return Promise.resolve(); 
} 
+0

루프에서 함수 호출이 비동기인지, 호출 규칙이 작동 하는지를 알아야합니다. 또한 약속에는 비동기적인 작업이 언제 완료되는지 알 수있는 마법의 힘이 없습니다. 그들은 비동기 작업이 완료 될 때 약속을 특별히 해결하거나 거절하는 경우에만 비동기 작업이 수행되는지 여부를 알 수 있습니다. 대신, 약속은 각 약속이 적절히 배관되면 비동기 작업을위한 모든 종류의 제어 흐름과 오류 처리 도구를 제공합니다. 루프의 모든 함수 호출, 특히 비동기 호출을 처리하고 있는지 문서화하십시오. – jfriend00

+0

@ jfriend00 관련 함수의 전체 섹션에서 추가했습니다. – LaLaLottie

+0

왜 cleanData에서'Promise.resolve()'를 호출하고 어떻게해야할까요? – DavidDomain

답변

2

는이 같은 약속 생성자를 사용합니다.

그러나 생성 된 약속 개체를 보류 상태로 영원히 남겨 두지는 않을 것입니다.

Constructing a promise을 참조하십시오.

+0

많은 코드가 있기 때문에 위의 코드는 보이지 않지만 다른 하나는'cleanData'에'Promise.resolve()'라고 쓰고 있습니다. 기능을 제공합니다. 'Promise.resolve();를 반환하는 것조차 상태를 변경하지 않습니다. 내가 약속들을 너무 일찍 배열에 넣기 때문에 그것입니까? – LaLaLottie

+3

@LaLaLottie 동적 Promise가있는 동안 정적 메서드 인'Promise.resolve()'또는'Promise.reject()'를 사용할 수 없기 때문에 정의 된'resolve (data) '및/또는'거부 (이유)'. 제가 제공 한 링크를보십시오. –

0

그것은 나에게 보이는 당신의 약속 배열이 정의되지 않은 : var에 약속을 = []; while 루프 전에.

var promise = new Promise(function (resolve, reject) { 

그것은 어딘가에이 블록 안에 당신이 약속을 해결하기 위해, resolve를 호출 및/또는 reject하는 것을 의미한다 :

+0

이것은 코드의 다른 부분에 있습니다. 나는 여기에 그것을 보여주지 않았다. – LaLaLottie

+0

이 외에도 많은 다른 많은 것들이 있습니다. OP는 루프에서 많은 비동기 작업을하는 것처럼 보입니다. 모든 작업은 적절하게 순서를 매기기 위해 약속으로 연결되어야합니다. – jfriend00

+0

내가 처음으로 알아 차 렸습니다. 그러나 배열에서 약속을 푸시하고 .all()을 사용하여 모두 호출 할 수 있습니다. – user3791775