提问人:the_gesslar 提问时间:8/13/2023 最后编辑:the_gesslar 更新时间:8/23/2023 访问量:93
Angular JS - 从异步操作返回结果
Angular JS - returning results from an async operation
问:
角度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 本身不支持使用现代 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;
}
}
评论
问题似乎在于 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}}
评论
您的问题是由于 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.item
updateItemInformation
$scope.previewContent
$applyAsync
上一个:任务如何并发运行?
评论