Angular JS - 从异步操作返回结果

Angular JS - returning results from an async operation

提问人:the_gesslar 提问时间:8/13/2023 最后编辑:the_gesslar 更新时间:8/23/2023 访问量:93

问:

角度JS - 1.6.9

我已经为此工作了几个小时,坦白地说,我没有在 Angular JS 中练习过,并希望得到一些指导。

我有一个元素,每次在表单的字段中更新信息时,它都会使用这些字段中的信息更新“预览窗格”,读取模板文件并替换值,将该信息打印到所述预览窗格。(注意:现在我每次以任何方式更新每个字段时都在阅读,我知道这很糟糕,稍后在我得到这个工作后,我将致力于缓存。所以,我不是在这部分寻求帮助,因为我知道我必须解决这个问题,以后会。

我已经以多种方式尝试过这个,这是最近的一次尝试,经过几个小时的摆弄,我只是不断得到我的控制台的结果。undefined

我非常有信心,这真的与我对异步事物的绝对误解有关。

我在 fillTemplate() 中有调试信息,它确实成功读取了文件,只是它没有进入浏览器。

HTML格式:

<div class="col text-monospace small shadow p-2 mb-2 pre-scrollable">
    {{updateItemInformation()}}
</div>


var app = angular.module('app', ['ngSanitize']);
app.controller('c', ($scope, $sce) => {
    $scope.updateItemInformation = async () => {
        let result ;

        const maxLineLength = 80;

        result = await fillTemplate($scope.item) ;

        console.log(result) ;

        return result ;
    };

    async function fillTemplate(item) {
        let result = "";

        const response = await fetch(`./templates/${item.category}.template`)
        const template = await response.text()

        if(!template) return "";

        return template ;
    }
AngularJS 异步

评论

0赞 Mark Clark 8/22/2023
您提到它已成功读取文件。就像您的提取返回成功一样?您是否尝试过将等待内容包装在 try-catch 中以确保它不会吞下错误?你可能会有更好的运气,而不是依赖模板来触发你的异步函数;绑定到作用域中的字符串,从 Update 函数更新该字符串,并通过事件触发更新。这样一来,您就不必为调试而与摘要周期作斗争。

答:

0赞 aUXcoder 8/21/2023 #1

AngularJS 本身不支持使用现代 JavaScript 框架中常用的 async/await 语法进行异步编程。使用该服务生成 promise 和 XMLHttpRequest。$q$http

以下示例只是有关以 AngularJS 方式构建 promise(异步调用)的一般参考。这不是一个字面上的解决方案。

var app = angular.module('app', ['ngSanitize']);
app.controller('c', ($scope, $sce, $http, $log) => {
  $ctrl.$onInit = () => {
    $scope.template = '';
    $scope.updateItemInformation = updateItemInformation;
  }

  function updateItemInformation() {
    fillTemplate($scope.item)
      .then(response => {
        $scope.template = response;
      })
      .catch(error => {
         $log.error(error)
      });
  }

  function fillTemplate(item) {
    const _deferred = $q.defer();
    $http.get(`./templates/${item.category}.template`)
      .then(response => {
        if (!response) _deferred.reject('Template not found');
        _deferred.resolve(response)
      })
      .catch(error => {
        _deferred.reject(error)
      })
    return _deferred.promise;
  }
}

评论

0赞 Mark Clark 8/22/2023
从本质上讲,没有。隐含地,是的。您仍然可以将 async-await 关键字与 $q 返回的 promise 一起使用。 stackoverflow.com/questions/62177913/...
0赞 Krishan Saini 8/23/2023 #2

问题似乎在于 AngularJS 无法识别您的异步函数所做的更新。您需要在异步操作后手动触发 Angular。digest cycle$scope.$apply()

下面是代码的更简化版本:

var app = angular.module('app', ['ngSanitize']);
app.controller('c', ($scope) => {
    $scope.updateItemInformation = async () => {
        const result = await fillTemplate($scope.item);
        console.log(result);
        $scope.$apply(() => {
            $scope.template = result;
        });
    };

    async function fillTemplate(item) {
        const response = await fetch(`./templates/${item.category}.template`);
        return response.text();
    }
});

在 HTML 中:

<div class="col text-monospace small shadow p-2 mb-2 pre-scrollable">
    {{template}}
    <button ng-click="updateItemInformation()">Refresh Preview</button>
</div>

添加了一个按钮来触发更新并在 中显示结果。希望这有帮助!继续前进;你走在正确的轨道上!👍{{template}}

评论

0赞 the_gesslar 8/23/2023
这似乎确实有效,但我想知道我是否可以像我希望的那样做到这一点,而无需单击按钮。我对这带来的开销感到满意。这不是一个大型应用程序。不过,我会奖励你这个回应的赏金!谢谢!
0赞 MaikeruDev 8/23/2023 #3

您的问题是由于 AngularJS 没有自动使用 native 重新消化视图。若要解决此问题,请使用范围变量来保存结果,并手动监视更改以更新视图。async/await

HTML格式

<div class="col text-monospace small shadow p-2 mb-2 pre-scrollable">
    {{ previewContent }}
</div>

JS格式:

var app = angular.module('app', ['ngSanitize']);
app.controller('c', function($scope) {

    $scope.previewContent = '';

    $scope.$watch('item', function() {
        updateItemInformation();
    });

    async function updateItemInformation() {
        $scope.previewContent = await fillTemplate($scope.item);
        $scope.$applyAsync(); // Ensure view updates
    }

    async function fillTemplate(item) {
        const response = await fetch(`./templates/${item.category}.template`);
        return response.text();
    }
});

用于检测 上的更改。当它发生更改时,会被调用、更新,然后视图会反映这些更改。$watch$scope.itemupdateItemInformation$scope.previewContent$applyAsync