递归调用promises

问题描述 投票:0回答:1

我已经在网上浏览了很长一段时间了。

我正在为一个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。其步骤如下:

  • 为当前项创建一个目录
  • 将文件下载到此目录
  • 将本地URL返回到下载的文件

之后的后续调用只会直接从磁盘返回图像(在检查它存在之后),不再下载。

javascript typescript recursion ionic-framework es6-promise
1个回答
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);
  }
}

并按预期工作。

© www.soinside.com 2019 - 2024. All rights reserved.