我可能会错过一些关于Angular的承诺,但我想知道一些事情:承诺是异步的吗?我不确定是否异步'是正确的词,但让我解释一下自己。
在我的代码中,我使用promises做了一个非常大的过程(读取和写入数百个大文件),同时我显示一个加载栏来观察过程的进度。我注意到即使我的代码在一个承诺中,它似乎也不是异步并冻结显示(我假设是由主线程管理)。
例如,在您可以在此Plnkr中找到的代码中,我想知道如何在大进程完成时让进度条移动。我理解为什么当我在主线程中调用它时它会冻结,而不是在我使用Angular的承诺时。
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $q) {
function hugeProcess () {
var i = 0;
var start = new Date().getTime();
while (i++ < 100000) {
console.log(i);
}
var end = new Date().getTime();
var time = end - start;
$scope.processTime = 'Done in ' + time + 'ms';
}
$scope.onClickStartHugeProcess = function () {
console.log('onClickStartHugeProcess');
hugeProcess();
};
$scope.onClickStartHugeProcessWithPromise = function () {
console.log('onClickStartHugeProcessWithPromise');
$q.when()
.then(function () {
return hugeProcess();
});
};
});
&#13;
答案 0 :(得分:1)
代码中的问题是您的hugeProcess
函数永远不会产生。所以是的,它是异步调用的(then
回调总是在Promises / A + promise实现中异步调用),但这不会改变调用它时hugeProcess
正在做什么,这会占用主要内容UI线程,使其在运行时不会发生任何其他事情。只有一个主要的UI线程,所有的JavaScript都运行在除web workers之外的那个主UI线程上。
要让hugeProcess
不这样做,你必须通过setTimeout
(或者可能内置于Angular中的内容)将其分解并让它在短暂延迟后自行调用。
作为Joe Clay points out,这段代码没有多大意义:
$q.when()
.then(function () {
return hugeProcess();
});
这是有效的:
setTimeout(hugeProcess, 0);
...因为没有参数的$q.when()
返回已解析的promise,并且向已解析的promise添加then
回调只会导致您的回调被尽快调用(但是异步;例如, then
在调用回调之前返回。
答案 1 :(得分:1)
所以,我发现了Web Workers,这是我使用它们的代码的第一个版本。
app.controller('MainCtrl', function($scope, $q) {
function hugeProcess () {
var i = 0;
var start = new Date().getTime();
while (i++ < 100000) {
console.log(i);
}
var end = new Date().getTime();
var time = end - start;
postMessage(time);
}
var blob = new Blob(["onmessage = " + hugeProcess.toString()]);
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
var worker = new Worker(blobURL);
worker.onmessage = function (message) {
$scope.processTime = 'Done in ' + message.data + 'ms';
$scope.$apply()
};
$scope.onClickStartHugeProcessWithPromise = function () {
console.debug('onClickStartHugeProcessWithPromise');
$q(function () {
worker.postMessage(''); // Start the worker.
});
};
});
我认为我没有正确使用它但是我做了我想要的...我发现Angular的包ng-webworker似乎混合了承诺和网络工作者,所以这正是我的意思寻找。
谢谢大家的帮助。
答案 2 :(得分:0)
Web Worker是正确的解决方案。我有类似的问题并开发了角度插件ng-vkThread来简化这类任务。
基本用法是:
/* function to execute in a thread */
function foo(n, m){
return n + m;
}
/* create an object, which you pass to vkThread as an argument*/
var param = {
fn: foo // <-- function to execute
args: [1, 2] // <-- arguments for this function
};
/* run thread */
vkThread.exec(param).then(
function (data) {
console.log(data); // <-- thread returns 3
},
function(err) {
alert(err); // <-- thread returns error message
}
);
- 瓦迪姆