2014-05-06 125 views
2

SO。處理異步調用的回調

我對處理Windows Azure Mobile Services異步調用Azure數據庫有一個問題。

現在,我發佈一個數組,我反過來在我的WAMS api端點循環的對象。

循環獲取數組中的當前對象,並將其與唯一ID一起推送到數據庫中。這將返回最後一個插入行的行ID,並且在回調函數中,我獲取這個以及實例化另一個異步調用。
在這裏,我然後插入最後一個插入的行id,連同數組的當前循環中的對象的一堆屬性。

但是,這似乎行爲異常,並在我的第二次異步調用中的所有列中插入相同的信息。

for (var i = 0; i < object.array.length; i++) { 

    var mssql = request.service.mssql, 
     prop1 = object.array[i].prop1, 
     prop2 = object.array[i].prop2, 
     user = object.user.userid; 

    mssql.query("exec stored_procedure ?, ?", [user, prop1], { 
     success: function (res) { 

      var insertedid = res[0]; 

      if (typeof insertedid === 'undefined') { 
       return; 
      } else { 
       insertedid = insertedid.ID; 
      } 

      mssql.query("exec stored_procedure_2 ?, ?", [insertedid, prop2], { 

       //success 

      }); 

     } 
    }); 
} 

我可能做一些完全錯誤的,因爲我不太喜歡我所生產的,但考慮到我的node.js的熟悉程度,這是它。

回答

2

這是async.js的一個可能的實現。如果你有兩個以上的屬性,你將需要動態地生成「insertPropX」函數,但這應該讓你開始。

var mssql = request.service.mssql; 
var user = object.user; 

function insertProp1(obj, cb) { 
    mssql.query("exec stored_procedure ?, ?", [user.userid, obj.prop1], { 
    success: function (res) { 
     var inserted = res[0]; 
     if (!inserted) { 
      return cb('prop1 not inserted for userid: ' + user.userid); 
     } 
     // pass the ID and the object to the next 
     // function in the "waterfall" chain 
     cb(null, inserted.ID, obj); 
    } 
    }); 
} 

function insertProp2(id, obj, cb) { 
    mssql.query("exec stored_procedure_2 ?, ?", [id, obj.prop2], { 
    success: function (res) { 
     var inserted = res[0]; 
     if (!inserted) { 
     return cb('prop2 not inserted for id: ' + id); 
     } 
     // since this is the last function in 
     // the "waterfall" chain, we don't need 
     // to pass anything along 
     cb(null); 
    } 
    }); 
} 

// for each object in the array... 
async.each(object.array, function iterator (obj, cb) { 
    // insert properties in order, passing the 
    // insertion ID as an argument 
    async.waterfall([ 
    insertProp1.bind(null, obj), 
    insertProp2 
    ], cb); 
}, function allDone (err) { 
    if (err) { 
    console.log(err); 
    } 
    // all done 
}); 
+0

感謝您對這樣一個完整的答案,這爲我提供了我需要看到的應該如何進行模式的知識。我在這裏答覆了兩個答案,但你的答案贏得了我的正確答案。因此,第一個異步任務中的回調函數會將信息傳遞給我接下來的迭代? – NicT

+1

很高興我能幫到你。正確的,瀑布中的每個函數都將參數傳遞給下一個函數。我強烈建議深入研究async.js庫,因爲它還有很多其他的很棒的功能。 –

+0

在定義應將哪些參數傳遞給瀑布函數時遇到了一些問題。我在上面的例子中有更多的論點。在每個async.each迭代中,我需要將4個參數傳遞給它們中的每個參數。 當他們通過我記錄的參數,返回錯誤的VAR async.each(interaction.Locs,功能(interaction.CID,位置,UNAME,組織,CB){ async.waterfall( [ insertCL.bind(null,交互。ControlID,location,uname,org), insertLOQ ], cb ); } – NicT

2

循環執行速度快於外部查詢完成並進行回調。因此,當每個回調執行時,它們都使用當前(和最終)值i而不是執行外部查詢時的值。

這是用一個簡單的循環像這樣的證明了這種情況說明:

for (var i = 0; i < 10; i++) { 
    setTimeout(function(){ 
     console.log('the value for i is', i); 
    },100); 
} 

你會看到,這個小程序不打印的順序,而是這10次:

the value for i is 10 

使用promises列出了幾種庫或選項)或類似async鏈接github上頁)工具是兩個潛在如此解決這個問題。

+0

+1 async.js –