2016-08-08 3 views
2

Я пытаюсь использовать обещания с петлями и вложенными функциями, которые находятся в пределах некоторых из этих циклов. У меня есть ряд функций, которые должны возвращать элементы списка SharePoint из вызовов REST - как только они выполняются, затем вызывается другая функция, которая использует данные, которые были возвращены.Использование обещаний с петлями и вложенными функциями

Поскольку в каждом из них имеется несколько списков, а затем несколько элементов списка, я использовал цикл while для каждого вызова REST, а оттуда данные (элементы списка) помещаются в объекты. Эти объекты помещаются в массив, и это то, что использует вторая функция.

У меня возникли проблемы с получением ответов от обещаний. Я думал, что у вас есть несколько обещаний, которые попадают в массив, а затем, наконец, используйте Promise.all, чтобы увидеть, все ли разрешено до использования then. Проблема в том, что все обещания остаются pending, так как я не возвращаю resolve правильно. См. Ниже.

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); 
     }); 
    } 

Потому что есть много функций, участвующих, так это порядок исполнения:

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 

Последнее, где я полагал, что я называю Promise.resolve() так, что конец линии.

В любом случае, это не работает. Я проверил другие темы, но я пытаюсь сделать это без использования каких-либо библиотек. Заранее спасибо.

Edit:

Полный соответствующий код:

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

Нам нужно знать, какие вызовы вашей функции в вашем цикле являются асинхронными и как работает их соглашение о вызовах. Кроме того, обещания НЕ имеют никаких волшебных способностей знать, когда делаются асинхронные действия. Они знают только, выполняется ли операция async, если вы решите или отклоните обещание, когда операция async будет выполнена. Вместо этого обещания предоставляют всевозможные средства управления потоком и обработки ошибок для асинхронных операций, как только каждое обещание будет соответствующим образом установлено. Пожалуйста, опишите, что делают ВСЕ функции в вашем цикле, особенно асинхронные. – jfriend00

+0

@ jfriend00 Я добавил в полный раздел задействованных функций. – LaLaLottie

+0

Почему вы вызываете 'return Promise.resolve()' внутри 'cleanData' и что это должно делать? – DavidDomain

ответ

2

При использовании обещание конструктор вроде этого:

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

Это подразумевает, что где-то внутри этого блока вы звоните resolve и/или reject, чтобы уладить обещание.

Но вы никогда не делаете этого, оставляя объект обещания в ожидающем состоянии навсегда.

См. Constructing a promise.

+0

Я все же это не показано выше, так как есть много кода, но я пишу 'Promise.resolve()' в 'cleanData', что является другим функции в пределах, указанных выше. Даже выполнение 'return Promise.resolve();' не меняет статус. Это потому, что я слишком рано выдвигаю обещания в массиве? – LaLaLottie

+3

@LaLaLottie вы не можете использовать 'Promise.resolve()' или 'Promise.reject()' там, это статические методы, в то время как у вас есть динамическое обещание, поэтому вы должны вызывать определенное 'разрешение (данные) 'и/или' reject (reason) '. См. Ссылку, которую я предоставил. –

0

Мне кажется, ваши обещания массив не определен: делать Var обещаниям = []; перед вашим циклом while.

+0

Он находится в другой части кода. Я не показывал его здесь. – LaLaLottie

+0

Есть много, много других вещей, кроме этого. У ОП, похоже, есть куча асинхронных операций в цикле, все из которых должны быть снабжены обещаниями, чтобы упорядочить вещи соответствующим образом. – jfriend00

+0

Это было первое, что я заметил. Тем не менее, вы можете отправлять обещания в массиве и называть их всеми .all() – user3791775