在以下情况下尝试解决延迟问题时遇到了一些问题
services.factory('MyService', ['$q',
function($q) {
var Foo = function() {
var deferred = $q.defer();
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 1024 * 1024, deferred.resolve, this.errorHandler);
return deferred.promise;
}
return {
Foo: Foo
}
}
]);
然后在控制器内:
var bar = new MyService.Foo().then(function(cb) {
console.log(cb)
});
如果我在requestFileSystem函数之外使用deferred.resolve,那么它可以完美地工作,但在上面的情况下没有任何反应。 PS:requestFileSystem函数的第三个参数是一个回调函数,它在文件系统就绪后就会获得它。
编辑: 这是吧:
Object {then: function, catch: function, finally: function}
requestFileSystem的第四个参数是一个记录到控制台文件系统API初始化错误的函数,但是在这种情况下它没有被调用,因为requestFileSystem成功所以应该调用deferred.resolve。如果我用正常函数替换延迟:
window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function(filesystem){
console.log(filesystem);
}, this.errorHandler);
然后正确返回filesystem对象:
DOMFileSystem {root: DirectoryEntry, name: "http_127.0.0.1_3000:Temporary"}
EDIT2:
我试图通过使用我自己的函数模拟requestFilesystem函数来进行简单的测试,并且它可以工作:
var Foo = function() {
var deferred = $q.defer();
asd(deferred.resolve)
return deferred.promise;
}
function asd(callback) {
callback('it works')
}
MyService.Foo().then(function(cb){
console.log(cb)
})
答案 0 :(得分:1)
基本问题是如何以及何时调用deferred.resolve
固定代码:
services.factory('MyService', ['$q','$rootScope',
function($q,$rootScope) {
var Foo = function() {
var deferred = $q.defer();
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
window.requestFileSystem(window.TEMPORARY, 1024 * 1024, function(result){
deferred.resolve(result);
$rootScope.$apply();//force angular to resolve promise
}, this.errorHandler);
return deferred.promise;
}
return {
Foo: Foo
}
}
]);
事情是,当您在角度生命周期之外调用'deferred.resolve'时(文件系统请求的回调超出了角度生命周期),您必须手动调用'$ rootScope。$ apply()'否则承诺将不会解决。
答案 1 :(得分:1)
github.com/maciel310/angular-filesystem
提供了更好的解决方案//wrap resolve/reject in an empty $timeout so it happens within the Angular call stack
//easier than .apply() since no scope is needed and doesn't error if already within an apply
function safeResolve(deferral, message) {
$timeout(function() {
deferral.resolve(message);
});
}
function safeReject(deferral, message) {
$timeout(function() {
deferral.reject(message);
});
}