我正在编写一个管理播放列表的应用程序。 基本上,我的实际逻辑是这样的
//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{}
感谢您的帮助!
正如已经指出的那样,正确使用的模式是 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; }