Angular延迟实现只输出循环的最后一个值

Angular deferred implementation only outputs last value of loop

本文关键字:最后一个 循环 输出 延迟 实现 Angular      更新时间:2023-09-26

我有一个自定义同步进程,在这个进程中,我按顺序将所有同步记录排队。当我的服务检索到超过1条同步记录时,它将处理它们,然后为每条成功的记录更新我的最后一次同步日期,或者在它失败时记录我的错误(不更新最后一次同步日期)并中止同步过程。

我实现了$q。全部来自AngularJS。下面是同步循环的一个子集:

    var processes = [];
    for (var i in data) {
        if (data[i] === null || data[i].TableName == null || data[i].Query == null || data[i].Params == null) {
            // Let's throw an error here...
            throw new TypeError("ERROR! The data retrieved from the download sync process was of an unexpected type.");
        }
        var params = data[i].Params;
        var paramsMassaged = params.replaceAll("[", "").replaceAll("]", "").replaceAll(", ", ",").replaceAll("'", "");
        var paramsArray = paramsMassaged.split(",");
        mlog.Log("Query: " + data[i].Query);
        mlog.Log("Params: " + paramsArray);
        if (data[i].TableName === "table1") {
            var process = $table1_DBContext.ExecuteSyncItem(data[i].Query, paramsArray);
            process.then(
                function () {
                    $DBConfigurations_DBContext.UpdateLastSyncDate(data[i].CreatedDate, function (response) {
                        mlog.Log(response);
                    });
                },
                function (response) {
                    mlog.LogSync("Error syncing record: " + response, "ERROR", data[i].Id);
                },
                null
            );
            processes.push(process);
        } else if (data[i].TableName === "table2") {
            var process = $table2_DBContext.ExecuteSyncItem(data[i].Query, paramsArray);
            process.then(
                function () {
                    $DBConfigurations_DBContext.UpdateLastSyncDate(data[i].CreatedDate, function (response) {
                        mlog.Log(response);
                    });
                },
                function (response) {
                    mlog.LogSync("Error syncing record: " + response, "ERROR", data[i].Id);
                },
                null
            );
            processes.push(process);
        } else {
            mlog.LogSync("WARNING! This table is not included in the sync process. You have an outdated version of the application. Table: " + data[i].TableName);
        }
    }
    $q.all(processes)
        .then(function (result) {
            mlog.LogSync("---Finished syncing all records");
        }, function (response) {
            mlog.LogSync("Sync Failure - " + response, "ERROR");
        });

ExecuteSyncItem函数示例:

ExecuteSyncItem: function (script, params) {
    window.logger.logIt("In the table1 ExecuteSyncItem function...");
    var primaryKey = params[params.length - 1];
    var deferred = $q.defer();
    $DBService.ExecuteQuery(script, params,
        function (insertId, rowsAffected, rows) {
            window.logger.logIt("rowsAffected: " + rowsAffected.rowsAffected);
            if (rowsAffected.rowsAffected <= 1) {
                deferred.resolve();
            } else {
                deferred.resolve(errorMessage);
            }
        },
        function (tx, error) {
            deferred.reject("Failed to sync table1 record with primary key: " + primaryKey + "; Error: " + error.message);
        }
    );
    return deferred.promise;
}

我遇到的问题是,如果有超过1个同步记录失败,那么这一行显示所有失败记录的相同值(不确定这是第一个失败记录,还是最后一个)。

mlog.LogSync("Error syncing record: " + response, "ERROR", data[i].Id);

我如何让它显示失败的特定记录的信息,而不是相同的消息"x"次?

正如comradburk所提到的,将进程包装在循环内的闭包中是一个很好的解决方案,但是有一个angular方法来解决这个问题。与使用本地的for-in循环不同,您可以通过angular.forEach()循环并遍历所有data元素。

var processes = [];
angular.forEach(data, function(item) {
    if (item === null || item.TableName == null || item.Query == null || item.Params == null) {
        // Let's throw an error here...
        throw new TypeError("ERROR! The data retrieved from the download sync process was of an unexpected type.");
    }
    var params = item.Params;
    var paramsMassaged = params.replaceAll("[", "").replaceAll("]", "").replaceAll(", ", ",").replaceAll("'", "");
    var paramsArray = paramsMassaged.split(",");
    mlog.Log("Query: " + item.Query);
    mlog.Log("Params: " + paramsArray);
    if (item.TableName === "table1") {
        var process = $table1_DBContext.ExecuteSyncItem(item.Query, paramsArray);
        process.then(
            function () {
                $DBConfigurations_DBContext.UpdateLastSyncDate(item.CreatedDate, function (response) {
                    mlog.Log(response);
                });
            },
            function (response) {
                mlog.LogSync("Error syncing record: " + response, "ERROR", item.Id);
            },
            null
        );
        processes.push(process);
    } else if (item.TableName === "table2") {
        var process = $table2_DBContext.ExecuteSyncItem(item.Query, paramsArray);
        process.then(
            function () {
                $DBConfigurations_DBContext.UpdateLastSyncDate(item.CreatedDate, function (response) {
                    mlog.Log(response);
                });
            },
            function (response) {
                mlog.LogSync("Error syncing record: " + response, "ERROR", item.Id);
            },
            null
        );
        processes.push(process);
    } else {
        mlog.LogSync("WARNING! This table is not included in the sync process. You have an outdated version of the application. Table: " + item.TableName);
    }
});
$q.all(processes)
    .then(function (result) {
        mlog.LogSync("---Finished syncing all records");
    }, function (response) {
        mlog.LogSync("Sync Failure - " + response, "ERROR");
    });

问题是由于你对i的闭包。当回调函数执行时,i的值将是for循环中的最后一个值。您需要将值i绑定到一个单独的、不变的值。最简单的方法是使用自调用函数。

for (var i in data) {
    (function(item) {
        // Put your logic in here and use item instead of i, for example
        mlog.LogSync("Error syncing record: " + response, "ERROR", data[item].Id
    })(i);
}

这里有一个很好的阅读为什么闭包会导致这个(这是一个相当常见的问题):Javascript臭名昭著的循环问题?