如何使用另一个类的方法“增强”一个 JS 类,而不扩展它?

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

我正在编写一个管理播放列表的应用程序。 基本上,我的实际逻辑是这样的

//define playlist props
class Playlist{
    public tracks = [];
}

class ApiPlaylist extends Playlist{
    //fill playlist withs (single page) data from API
    public async loadPage(paginationSettings){
        const pageTracks = await...
        this.tracks = [...this.tracks,...pageTracks]; //concat tracks
    }
}

class Paginated extends ApiPlaylist{
    private iterations = 0;
    private endReached = false;
    public async loadAll(){
        while (!this.endReached){
            this.loadNext();
        }
    }
    public async loadNext(){
        this.iterations++;
        await this.loadPage(); //call ApiPlaylist method
        if(...){
            this.endReached = true; //stop iterating
        }
    }

}

const playlist = new Paginated();
playlist.loadAll();

它有效。

但是,如果我要获取与播放列表无关的不同其他分页数据怎么办?

我想将

PaginatedPlaylist
中的机制与其他类一起使用,而不必重复它。

实际上,

Paginated
延伸了
ApiPlaylist
。 有没有一种简单的方法来实现从
Paginated
ApiPlaylist
的方法而不使用
extends

类似的东西

class ApiPlaylist [implements] Paginated{}
class ApiPost [implements] Paginated{}
class ApiPage [implements] Paginated{}

感谢您的帮助!

javascript typescript class design-patterns
1个回答
0
投票

正如已经指出的那样,正确使用的模式是 mixin 或基于特征的组合。

下一个提供的示例代码演示了基于函数的 mixin 的用法,该 mixin 实现并应用了可加载打包轨道的功能/行为。

async function mockedFetch(paginationSettings) {
  console.log({ paginationSettings });

  console.log('... fetching ...');

  return new Promise(
    resolve => setTimeout(resolve, 1_500, ['foo', 'bar', 'baz']),/*
    reject => { handle reject },*/
  );
}


// implementation of the actual context-aware `loadPage` method.
async function fetchTracksAndPushIntoBoundTrackList(paginationSettings) {
  const pageTracks = await mockedFetch(paginationSettings);

  this.tracks.push(...pageTracks);
}
// function based mixin.
function withLoadablePackinatedTracks() {
  this.loadPage = fetchTracksAndPushIntoBoundTrackList.bind(this);
}


// base class.
class Playlist {
  constructor () {

    this.tracks = [];
  }
}
// sub-classing ...
class PaginatedPlaylist extends Playlist {
  constructor () {

    // inheritance.
    super();

    // composition ... applying the function based mixin.
    withLoadablePackinatedTracks.call(this);
  }
}


(async () => {

  const paginatedList = new PaginatedPlaylist;

  console.log({ tracks: paginatedList.tracks });

  await paginatedList.loadPage({ tracks: 3 });

  console.log({ tracks: paginatedList.tracks });

  await paginatedList.loadPage({ tracks: 3 });

  console.log({ tracks: paginatedList.tracks });

})();
.as-console-wrapper { min-height: 100%!important; top: 0; }

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