重构以下 javascript 代码有什么好的建议吗?

Any good suggestions for refactoring the following javascript code?

对于重构此代码的更简洁的方法有任何想法或建议吗?

也许是循环解决方案或类似的解决方案?

this._featuredImage = '../../../../../../../../content/images/' + this.post.slug + '.jpg';
this._checkImage(this._featuredImage, function() { // Image exists
  this.featuredImage = this._featuredImage;
}.bind(this), function() { // Image doesn't exist
  this._featuredImage = '../../../../../../../../content/images/' + this.post.slug + '.png';
  this._checkImage(this._featuredImage, function() { // Image exists
    this.featuredImage = this._featuredImage;
  }.bind(this), function() { // Image doesn't exist
    this._featuredImage = '../../../../../../../../content/images/' + this.post.datestamp + '.jpg';
    this._checkImage(this._featuredImage, function() { // Image exists
      this.featuredImage = this._featuredImage;
    }.bind(this), function() { // Image doesn't exist
      this._featuredImage = '../../../../../../../../content/images/' + this.post.datestamp + '.png';
      this._checkImage(this._featuredImage, function() { // Image exists
        this.featuredImage = this._featuredImage;
      }.bind(this), function() { // Image doesn't exist
        this.featuredImage = false;
      }.bind(this));
    }.bind(this));
  }.bind(this));
}.bind(this));

谢谢,我希望这是有道理的。

是的,某种循环,但是因为您的 _checkImage 函数是异步的,所以它不可能是 forwhile:

var images = [this.post.slug + '.jpg', this.post.slug + '.png', this.post.datestamp + '.jpg', this.post.datestamp + '.png'];
var index = 0;
setFeaturedImage(this);
function setFeaturedImage(t) {
    if (index < images.length) {
        t._featuredImage = '../../../../../../../../content/images/' + images[index];
        t._checkImage(t._featuredImage,
            function() { // Image exists
              t.featuredImage = t._featuredImage;
            },
            function() { // Image doesn't exist
              ++index;
              setFeaturedImage(t);
            }
        );
    }
}

我不太明白你为什么要将正在测试的图像保存为_featuredImage。如果没有必要,我们可以去掉它:

var images = [this.post.slug + '.jpg', this.post.slug + '.png', this.post.datestamp + '.jpg', this.post.datestamp + '.png'];
var index = 0;
setFeaturedImage(this);
function setFeaturedImage(t) {
    if (index < images.length) {
        var image = '../../../../../../../../content/images/' + images[index];
        t._checkImage(image,
            function() { // Image exists
              t.featuredImage = image;
            },
            function() { // Image doesn't exist
              ++index;
              setFeaturedImage(t);
            }
        );
    }
}

您可以通过将 this 存储在变量中而不是使用 Function.prototype.bind

来重构和简化代码
var prefix = '../../../../../../../../content/images/';
var that = this;

function activateImageIfExists(image, elseCall)  {
    var fullImagePath = prefix + image;
    that._checkImage(fullImagePath , function() { that.featuredImage = fullImagePath; }, elseCall);
}

activateImageIfExists(that.post.slug + '.jpg', function() {
    activateImageIfExists(that.post.slug + '.png', function() {
        activateImageIfExists(that.post.datestamp + '.jpg', function() {
            activateImageIfExists(that.post.datestamp + '.png', function() {
                that.featuredImage = false;
            });
        });
    });
});

如果您不需要支持旧浏览器,您可以使用箭头功能

var prefix = '../../../../../../../../content/images/';

var activateImageIfExists = (image, elseCall)  => {
    var fullImagePath = prefix + image;
    this._checkImage(fullImagePath, () =>  this.featuredImage = fullImagePath , elseCall);
}

activateImageIfExists(this.post.slug + '.jpg', () => 
activateImageIfExists(this.post.slug + '.png', () => 
activateImageIfExists(this.post.datestamp + '.jpg', () => 
activateImageIfExists(this.post.datestamp + '.png', () =>  this.featuredImage = false ))));

我将从更改硬编码字符串和乍一看重复的代码开始:

this.setFeaturedImage = function(newImage) {

  this.featuredImage = newImage;
}

this.unsetFeatureImage = function() {
  this.featuredImage = false;
}

this.imagesRoot = '../../../../../../../../content/images/';
this.fileExtensions = ['jpg' => '.jpg', 'png' => '.png'];

this.getPostSlugImage = function(extension) {
    return this.imagesRoot + this.post.slug + fileExtensions[extension];
}

this.getPostDatestampImage = function(extension) {
    return this.imagesRoot + this.post.datestamp + fileExtensions[extension];
}

然后我更改了对此对象方法的匿名函数调用。 在这里,我看到该方法在链中失败时调用自己。所以我将它们更改为在失败时调用 unsetFeaturedImage 并返回 false

this.trySetPostSlugJpgImage = function() {
  this._checkImage(this.getPostSlugImage('jpg'), this.setFeaturedImage(this.getPostSlugImage('jpg')).bind(this), unsetFeatureImage.bind(this));
  if(this.featuredImage == false) return false;
}

this.trySetPostSlugPngImage = function() {
  this._checkImage(this.getPostSlugImage('png'), this.setFeaturedImage(this.getPostSlugImage('png')).bind(this), unsetFeatureImage.bind(this));
  if(this.featuredImage == false) return false;
}

this.trySetPostDatestampJpgImage = function() {
  this._checkImage(this.getPostDatestampImage('jpg'), this.setFeaturedImage(this.getPostDatestampImage('jpg')).bind(this), unsetFeatureImage.bind(this));
  if(this.featuredImage == false) return false;
}

this.trySetPostDatestampPngImage = function() {
  this._checkImage(this.getPostDatestampImage('png'), this.setFeaturedImage(this.getPostDatestampImage('png')).bind(this), unsetFeatureImage.bind(this));
  if(this.featuredImage == false) return false;
}

结果我有:

if(!this.trySetPostSlugJpgImage())
  if(!this.trySetPostSlugPngImage())
    if(!this.trySetPostDatestampJpgImage())
      if(!this.trySetPostDatestampPngImage())

我们可以用简单的名字关闭函数并在我们的系统中使用

const path = '../../../../../../../../content/images/';
const images = [
    path + this.post.slug + '.jpg',
    path + this.post.slug + '.png',
    path + this.post.datestamp + '.jpg',
    path + this.post.datestamp + '.png',
];
const c1 = () => this.featuredImage = this._featuredImage;
const c2 = () => {
    let box = images.shift();
    this._featuredImage = box;
    this._checkImage(box, c1, box? c2 : () => {
        this.featuredImage = false;
    });
};

c2();