2016-08-08 5 views
2

私は、それらのループの中にあるループとネストされた関数で約束を使用しようとしています。私は、REST呼び出しからSharePointリスト項目を戻すことになっている一連の関数を持っています。実行されたら、戻されたデータを使用する別の関数が呼び出されます。ループとネストされた関数での約定を使用する

複数のリストがあり、それぞれに複数のリスト項目があるため、whileループを使用して各REST呼び出しを行い、そこからデータ(リスト項目)をオブジェクトに入れます。それらのオブジェクトは配列に配置され、それはその2番目の関数が継続するために使用するものです。

私は約束からの回答を受け取ることができません。私は配列にプッシュされる複数の約束を持っていると思っていたのですが、最後に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

あなたはこのような約束のコンストラクタを使用する場合:

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

をそれは約束を解決するために、どこかでこのブロック内であなたがresolveおよび/またはrejectを呼び出していることを意味します。

しかし、作成した約束オブジェクトを永久に保留状態にしておくことは決してありません。

Constructing a promiseを参照してください。

+0

コードはたくさんあるので上には表示されていませんが、私は 'cleanData'に' Promise.resolve() 'を書きます上記の投稿内の'Promise.resolve();を返すことさえ、ステータスを変更していません。それはあまりにも早く配列に約束を押しているからですか? – LaLaLottie

+3

@LaLaLottie動的Promiseを持っている間は 'Promise.resolve()'や 'Promise.reject()'を静的メソッドとして使うことはできませんので、定義された 'resolve(data) 'および/または' reject(理由) '私が提供したリンクを参照してください。 –

0

あなたの約束の配列が定義されていない私には思える:VARの約束を行います= [];あなたのwhileループの前に。

+0

これはコードの別の部分にあります。私はここにそれを示さなかった。 – LaLaLottie

+0

これ以外にも多くの、他の多くのものが間違っています。 OPは、ループ内で一連の非同期操作をしているように見えますが、すべてを適切に順序づけるために約束する必要があります。 – jfriend00

+0

私が気づいたのはこれが最初のことでした。しかし、配列内の約束をプッシュして、すべてを.all()で呼び出すことができます。 – user3791775

関連する問題