2017-11-12 5 views
0

特に、配列内のすべての項目に対して複数の非同期操作を実行する必要がある場合は、Defferedオブジェクトを扱うことに頭を抱えようとしています。下のコードでは、完成した後に非同期配列の結果にアクセスできるようにしたいのですが、私の場合は結果配列です。非同期関数の結果を除外オブジェクトとして渡す方法

  • コード

    以下
    1. たListData関数iが操作しようとする配列されたソースデータを導出説明します。
    2. 上記アレイ内のすべてのアイテムについて
    3. getPictureComplete1 perfroms非同期動作(ListDataWithPicture)は、ステップ2のアイデアは、ステップ1からアレイ内のすべての項目に画像のURLを追加することであったし、新しいを使用します4
    4. ステップへの入力として配列は、ページに画像を印刷またはアレイ

var mydeferred = $.Deferred(); 
 
var ListData = function(){  
 
    listName = 'TeamInfo'; 
 
     $.ajax({ 
 
      url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+listName+"')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id", 
 
      type: "GET", 
 
      headers: { "ACCEPT": "application/json;odata=verbose" }, 
 
      success: onQuerySucceded, 
 
      error: onQueryFailed 
 
     }); 
 
     return mydeferred.promise(); 
 
    } 
 
var ListDataWithPicture = function(userId, callback) { 
 
     // execute AJAX request 
 
      $.ajax({ 
 
       url: _spPageContextInfo.siteAbsoluteUrl + "/_api/web/SiteUserInfoList/items?$filter=Id eq " + userId + "&$select=Picture", 
 
       type: "GET", 
 
       async: false, 
 
       headers: { "ACCEPT": "application/json;odata=verbose" }, 
 
       success: function(data){ 
 
        console.log("Starting async operation for " + userId); 
 
        var pictureLink = ""; 
 
        var mydata = callback(data.d.results[0].Picture.Url);      
 
        return mydata 
 
       }, 
 
      error: onQueryFailed 
 
      });    
 
        
 
    } 
 
    
 
function onQuerySucceded (data){ 
 
    var PeopleCompleteList = []; 
 
    for (i=0; i< data.d.results.length; i++) { 
 
        //check if the user exists if he does store the following properties name,title,workphone,email 
 
        if(data.d.results[i]['Name'] != null){ 
 
         personName = data.d.results[i]['Name'].Name.split('|')[2]; 
 
         userName = data.d.results[i]['Name']['Name']; 
 
         UserTitle = data.d.results[i]['Name']['Title']; 
 
         UserphoneNumber = data.d.results[i]['Name']['WorkPhone']; 
 
         UserEmail = data.d.results[i]['Name']['EMail']; 
 
         Id = data.d.results[i]['Name']['Id']; 
 
         PeopleCompleteList.push(PersonConstructor(personName, UserTitle, UserphoneNumber,UserEmail,Id)); 
 
        } 
 
       } 
 
    mydeferred.resolve(PeopleCompleteList); 
 
} 
 
    
 
function getPictureComplete1 (data){ 
 
      var def = new $.Deferred(); 
 
      var results = []; 
 
      var expecting = data.length; 
 
      data.forEach(function(entry, index) { 
 
       //this is the asynchronous function 
 
       ListDataWithPicture(entry.UserId, function(result) { 
 
        results[index] = {imageUrl: result, UserId: entry.UserId, name: entry.name, Title: entry.Title, phoneNumber: entry.phoneNumber, Email: entry.Email}; 
 
        //console.log(result); 
 
        if (--expecting === 0) { 
 
        // Done! 
 
        console.log("Results:", results); //this works succeffully from here 
 
        def.resolve(); 
 
        return results 
 
        //mydeferred.resolve(results); 
 
       } 
 
       }); 
 

 
      }); 
 
      return mydeferred.promise(); 
 
} 
 

 

 
$(function() { 
 
     ListData().then(function(data){ 
 
      //how can i access the results array in this function after it has completed??   
 
      var value = getPictureComplete1 (data); 
 
      //the line below results undefined,which i understand because the getPictureComplete1 function may not have completed at the time 
 
      console.log(value); 
 
    });
に追加の操作を実行することができ

答えて

0

これは非同期操作ですので、あなたがLineDataであなたのajax呼び出しから結果の配列へのアクセスを持っている唯一の時間は、あなたの中にsuccessプロパティに割り当てられたonQuerySucceded機能の範囲内でありますajaxの設定。ここで定義する関数は、応答が正常に受信された後に起動されます。

遅延プロミスを確立するときに、どのデータがプロミスを解決するかを定義する必要があります。 resolveメソッドに渡すものは、その後のブロック内のパラメータとして利用可能になります。

私はあなたの例で定義されたonQuerySuccededを見ていないんだけど、それはこのようなものになります。今

var ListData = function(){ 
    var mydeferred = $.Deferred(); 
    listName = 'TeamInfo'; 
    $.ajax({ 
     url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+listName+"')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id", 
     type: "GET", 
     headers: { "ACCEPT": "application/json;odata=verbose" }, 
     success: function onQuerySuccess(data) { 
      mydeferred.resolve(data); 
     }, 
     error: onQueryFailed 
    }); 
    return mydeferred.promise(); 
} 

は、呼び出しが成功した後、約束はデータで解決されます。だから、このようなものが可能です:

ListData() 
    .then(function (data) { 
     // do something with the data 
    }) 

同様に、あなたは延期の約束のために拒絶例が何であるかを定義することになるでしょう。たとえば、ajax呼び出しが成功しない可能性があります。このためには、deferredオブジェクトでrejectメソッドを使用します。例えば

var ListData = function(){  
    var mydeferred = $.Deferred(); 
    listName = 'TeamInfo'; 
    $.ajax({ 
     url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+listName+"')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id", 
     type: "GET", 
     headers: { "ACCEPT": "application/json;odata=verbose" }, 
     success: function onQuerySuccess(data) { 
      mydeferred.resolve(data); 
     }, 
     error: function onQueryFailed(error) { 
      mydeferred.reject(error); 
     } 
    }); 
    return mydeferred.promise(); 
} 

これは解決と同様に動作しますが、それ以降のcatchまたはfailブロックに解決されます。だから、このようなものは、あなたが直接これらの特性としてmydeferred.resolvemydeferred.rejectを設定することができ、さらに簡単に言えば

LineData() 
    .then(function (data) { 
     // it was successful, do something with the data 
    }) 
    .catch(function (error) { 
     // There was an error. The then block was not called. 
     // Do something with the error. 
    }) 

に動作します。これと同じように:

var ListData = function(){  
    var mydeferred = $.Deferred(); 
    listName = 'TeamInfo'; 
    $.ajax({ 
     url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('"+listName+"')/items?$select=Name/Title,Name/Name,Name/Id,Name/EMail,Name/WorkPhone&$expand=Name/Id", 
     type: "GET", 
     headers: { "ACCEPT": "application/json;odata=verbose" }, 
     success: mydeferred.resolve, 
     error: mydeferred.reject 
    }); 
    return mydeferred.promise(); 
} 

あなたは、それはまた、あなたが必要とするデータとの約束を返すように、あなたのListDataWithPicture機能と似た何かをしたいでしょう:

var ListDataWithPicture = function(userId, callback) { 
    var deferred = $.Deferred(); 
    $.ajax({ 
     url: _spPageContextInfo.siteAbsoluteUrl + "/_api/web/SiteUserInfoList/items?$filter=Id eq " + userId + "&$select=Picture", 
     type: "GET", 
     async: false, 
     headers: { "ACCEPT": "application/json;odata=verbose" }, 
     success: function(data){ 
      deferred.resolve(data.d.results[0].Picture.Url) 
     }, 
     error: deferred.reject 
    });    
    return deferred.promise(); 
} 

これは、あなたがこのような何かを行うことができます:あなたは、アレイ内の各項目にaynchronous操作を実行したいので

LineData() 
    .then(function (data) { 
     // performing on just the first result: 
     return ListDataWithPicture(data[0]); 
    }) 
    .then(function (url) { 
     // do something with the result 
    }) 
    .catch(function (error) { 
     // do something with the error 
    }); 

、私は実行し、解決Promise.allを使用することをお勧めします約束の配列。ここで

LineData() 
    .then(function (data) { 
     // create a map of promises 
     var promises = data.map(function (item) { 
      return ListDataWithPicture(item); 
     }); 
     return Promise.all(promises); 
    }) 
    .then(function (urls) { 
     // urls will be an array of urls resolved from calling 
     // ListDataWithPicture on each item in the array resolved 
     // from above 
    }) 
    .catch(function (error) { 
     // do something with the error 
    }); 

はもっと学ぶためにいくつかの良いリソースです:

+0

おかげエリック、したListData()関数は、大丈夫働く私は繰延オブジェクトにアクセスすることができ、どこで私は苦労している次の ".then()"どこに渡されたオブジェクトの各項目の非同期関数(ListDataWithPicture)を実行する必要があります.. '(--expecting === 0){//行うネ! console.log( "結果:"、結果);私は各項目の非同期操作が完了したと言うことができるコード内のポイントがありますが、私はどのようにして次に次の.thenに渡すことができる遅延オブジェクトを確立するのか分かりません(これは、ここでは からsucceffullyを働きます) )。 – GottiJay

+0

私はちょうどこれを解決する必要が私の答えを更新しました。 Promise.allを使用してアイテムの配列に対して非同期関数を実行する場合。その結果は、あなたが約束を返すと仮定したときに次に利用できるようになります。 –

関連する問題