Javascriptclosures不起作用

我读过这些问题:

  • 循环中的JavaScript闭包 – 一个简单实用的例子
  • JavaScriptclosures如何工作?
  • 如何将JSvariables的值(不是引用)传递给函数?

并试图应用他们的解决scheme(以及至less二十二个其他实现),他们都没有工作。

这里是循环的函数:

ExecuteQueryWhereQueryAndParamsBothArrays: function (queryArray, paramsArray, idsArray, success, fail, errorLogging) { var hasError = false; $rootScope.syncDownloadCount = 0; $rootScope.duplicateRecordCount = 0; $rootScope.db.transaction(function (tx) { for (var i = 0; i < paramsArray.length; i++) { window.logger.logIt("id: " + idsArray[i]); var query = queryArray[i]; var params = paramsArray[i]; var id = idsArray[i]; tx.executeSql(query, params, function (tx, results) { incrementSyncDownloadCount(results.rowsAffected); }, function(tx, error) { if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) { incrementDuplicateRecordCount(1); return false; } // this didn't work: errorLogging(tx, error, id); // so I wrapped in in an IIFE as suggested: (function(a, b, c) { errorLogging(a, b, idsArray[c]); })(tx, error, i); return true; }); } }, function () { fail(); }, function () { success(); }); 

这里是写我的消息的错误logging函数(注意,我不能在相同的JavaScript文件中“写”消息,因为我需要[angular]注入另一个引用到这个文件,它会导致一个通知参考和代码将不会运行)

 var onError = function (tx, e, syncQueueId) { mlog.LogSync("DBService/SQLite Error: " + e.message, "ERROR", syncQueueId); }; 

还有什么方法可以阻止它返回我的同步logging的最后一个“id”(当它只是第一个有错误的logging)?

 … var i … async(function() { … // errorLogging(tx, error, id); (function(a, b, c) { errorLogging(a, b, idsArray[c]); })(tx, error, i); … }) 

这是没用的,因为ivariables已经在那里有错误的值。 你需要在整个asynchronouscallback中使用wrapper,closures所有在asynchronouscallback中使用的variables,但是会被同步循环修改。

最简单的方法就是简单地包装完整的循环体,然后closures迭代variables:

 for (var i = 0; i < paramsArray.length; i++) (function(i) { // here var query = queryArray[i]; var params = paramsArray[i]; var id = idsArray[i]; window.logger.logIt("id: " + id); tx.executeSql(query, params, function (tx, results) { incrementSyncDownloadCount(results.rowsAffected); }, function(tx, error) { if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) { incrementDuplicateRecordCount(1); return false; } errorLogging(tx, error, id); return true; }); }(i)); // and here 

你也可以传递循环中构造的所有variables(并依赖于迭代variables)作为闭包参数。 在你的情况下,它可能是这样的:

 for (var i = 0; i < paramsArray.length; i++) { (function(query, params, id) { // here window.logger.logIt("id: " + id); tx.executeSql(query, params, function (tx, results) { incrementSyncDownloadCount(results.rowsAffected); }, function(tx, error) { if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) { incrementDuplicateRecordCount(1); return false; } errorLogging(tx, error, id); return true; }); }(queryArray[i], paramsArray[i], idsArray[i])); // here } 

或者你确定asynchronouscallback,并只包装:

 for (var i = 0; i < paramsArray.length; i++) { window.logger.logIt("id: " + idsArray[i]); tx.executeSql(queryArray[i], paramsArray[i], function (tx, results) { incrementSyncDownloadCount(results.rowsAffected); }, (function(id) { // here return function(tx, error) { // ^^^^^^ and here if (error.message.indexOf("are not unique") > 0 || error.message.indexOf("is not unique") > 0) { incrementDuplicateRecordCount(1); return false; } errorLogging(tx, error, id); return true; }; }(idsArray[i]))); // and here }