我已经在网上浏览了很长一段时间了。
我正在为一款Ionic应用程序制作一个Angular服务原型。此服务的目的是下载图像。现在这是一个问题,在标准JS中,我想通过一些递归调用来解决,以避免重复代码。
我已经尝试用承诺写下它,让我对Promises的概念感到羞愧,这让我很难过。
请考虑以下代码:
public getBgForName = (name: string) => {
name = name.toLowerCase();
var instance = this;
var dir = this.file.dataDirectory;
return new Promise(function (fulfill, reject) {
instance.file.checkDir(dir, name).then(() => {
// directory exists. Is there a bg file?
dir = dir + '/' + name + '/';
instance.file.checkFile(dir, 'bg.jpg').then(() => {
console.log('read file');
fulfill(dir + '/' + 'bg.jpg')
}, (err) => {
// dl file and re-call
console.log('needs to download file!')
instance.transfer.create().download(encodeURI('https://host.tld/'+name+'/bg.jpg'), dir + 'bg.jpg', true, {})
.then((data) => {
return instance.getBgForName(name).then((url) => {return url});
}, (err) => {
console.log(err)
})
})
}, (err) => {
// create dir and re-call
instance.file.createDir(dir, name, true).then(() => {
instance.getBgForName(name).then((url) => {fulfill(url)});
})
})
});
}
承诺,在被召唤时 - 永远不会完全解决。我认为,在阅读this article之后,问题在于我的承诺解决了没有正确传递到“原始”承诺链 - 所以它解决了解决级别,但不是一直到顶部。当确保以下内容时,承诺正确解决了这一点:
目录已创建
该文件已下载
所以我认为返回语句在某种程度上打破了这里的链接,导致承诺在第一次递归调用后没有得到解决。
以递归方式调用promise的正确方法是什么,确保原始调用者在准备好后收到结果?
编辑:根据David B.的建议概述所需的结果。 代码应该是在项列表上调用的函数。对于每个项目,都有一个可用的背景图像,存储在服务器上。此背景图像将在本地缓存。在这里使用递归调用的目的是,无论状态(下载,未下载),函数调用将始终返回本地文件系统上的图像的URL。其步骤如下:
答案 0 :(得分:0)
在阅读了async / await over promises(并且爱上了更清晰的语法)的好处之后,我用async / await重新编写了它。重构的(但不是完美的!)代码如下所示:
public getBgForName = async (name: string) => {
name = name.toLowerCase();
let instance = this;
let dir = this.file.dataDirectory;
try{
await instance.file.checkDir(dir, name)
dir = dir + name + '/';
try{
await instance.file.checkFile(dir, 'bg.jpg')
return dir + 'bg.jpg';
}catch(err) {
// download file
await instance.transfer.create().download(encodeURI('https://host.tld/'+name+'/bg.jpg'), dir + 'bg.jpg', true, {})
return this.getBgForName(name);
}
}catch(err) {
// not catching the error here since if we can't write to the app's local storage something is very off anyway.
await instance.file.createDir(dir, name, true)
return this.getBgForName(name);
}
}
按预期工作。