/**
* @file 中間件.js
* @module 中間件
*/
從'../utils/obj.js'導入{分配};
從 '../utils/string-cases.js' 導入 {toTitleCase};
const 中間件 = {};
常量中間件實例 = {};
導出常量終止符 = {};
/**
* 中間件對像是一個普通的 JavaScript 對象,它有一些方法
* 匹配允許列表中的 {@link Tech} 方法
* {@link 模塊:中間件。允許 | 吸氣器},
* {@link 模塊:中間件. 允許的設置器 | 設置器} 和
* {@link 模塊:中間件。允許調解器 | 調解器}。
*
* @typedef {Object} 中間件對象
*/
/**
* 一個中間件工廠函數,應該返回一個
* {@link 模塊:中間件〜中間件對象 | 中間件對象}。
*
* 這個工廠會在需要的時候為每個玩家調用,和玩家一起
* 作為參數傳入。
*
* @callback 中間件工廠
* @param {Player} 播放器
* Video.js 播放器。
*/
/**
* 定義播放器應通過工廠函數使用的中間件
* 返回一個中間件對象。
*
* @param {string} 類型
* 要匹配的 MIME 類型或所有 MIME 類型的“*”。
*
* @param {MiddlewareFactory} 中間件
* 將執行的中間件工廠函數
* 匹配類型。
*/
導出函數使用(類型,中間件){
中間件[類型] = 中間件[類型] || [];
中間件[類型].push(中間件);
}
/**
* 按類型(或所有中間件)獲取中間件。
*
* @param {string} 類型
* 要匹配的 MIME 類型或所有 MIME 類型的“*”。
*
* @return {函數[]|未定義}
* 一組中間件,如果不存在則為 `undefined`。
*/
導出函數 getMiddleware(type) {
如果(類型){
返回中間件[類型];
}
返回中間件;
}
/**
*通過遞歸任何中間件異步設置源
* 匹配中間件並在每個中間件上調用 `setSource`,傳遞
* 以前每次返回的值。
*
* @param {Player} 播放器
* {@link Player} 實例。
*
* @param {Tech~SourceObject} 源
* 源對象。
*
* @param {函數}
* 下一個要運行的中間件。
*/
導出函數 setSource(player, src, next) {
player.setTimeout(() => setSourceHelper(src, middlewares[src.type], next, player), 1);
}
/**
* 設置技術後,將技術傳遞給每個中間件的 setTech 方法。
*
* @param {Object[]} 中間件
* 一組中間件實例。
*
* @param {技術}技術
* Video.js 技術。
*/
導出函數 setTech(中間件,技術){
middleware.forEach((mw) => mw.setTech && mw.setTech(tech));
}
/**
* 首先通過每個中間件調用技術上的吸氣劑
* 從右到左給玩家。
*
* @param {Object[]} 中間件
* 一組中間件實例。
*
* @param {技術} 技術
* 目前的技術。
*
* @param {string} 方法
* 一個方法名。
*
* @return {混合}
* 中間件攔截後技術的最終值。
*/
導出函數 get(中間件、技術、方法){
return middleware.reduceRight(middlewareIterator(method), tech[method]());
}
/**
* 獲取給玩家的參數並在每個參數上調用 setter 方法
* 從左到右到技術的中間件。
*
* @param {Object[]} 中間件
* 一組中間件實例。
*
* @param {技術}技術
* 目前的技術。
*
* @param {string} 方法
* 一個方法名。
*
* @param {混合} 參數
* 在技術上設置的值。
*
* @return {混合}
* `tech` 的`method` 的返回值。
*/
導出函數集(中間件、技術、方法、參數){
返回技術[方法](middleware.reduce(middlewareIterator(method), arg));
}
/**
* 獲取給玩家的參數並調用
* 每個中間件上的方法從左到右。
*
* 然後,在tech上調用傳入的方法,返回結果不變
* 返回給播放器,通過中間件,這次是從右到左。
*
* @param {Object[]} 中間件
* 一組中間件實例。
*
* @param {技術}技術
* 目前的技術。
*
* @param {string} 方法
* 一個方法名。
*
* @param {混合} 參數
* 在技術上設置的值。
*
* @return {混合}
* `tech` 的`method` 的返回值,不管
* 中間件的返回值。
*/
導出函數調解(中間件、技術、方法、arg = null){
const callMethod = 'call' + toTitleCase(方法);
const middlewareValue = middleware.reduce(middlewareIterator(callMethod), arg);
const terminated = middlewareValue === TERMINATOR;
// 棄用。`null` 返回值應該返回 TERMINATOR 到
// 如果 techs 方法實際上返回 null,則防止混淆。
const returnValue = 終止?空:技術[方法](中間件值);
executeRight(中間件,方法,returnValue,終止);
返回返回值;
}
/**
* 枚舉允許的 getter,其中鍵是方法名稱。
*
* @type {對象}
*/
export const allowedGetters = {
緩衝的:1、
當前時間:1、
持續時間:1、
靜音:1、
玩過:1、
暫停:1、
可尋:1、
體積:1、
結束:1
};
/**
* 允許的 setter 的枚舉,其中鍵是方法名稱。
*
* @type {對象}
*/
導出常量 allowedSetters = {
設置當前時間:1、
設置靜音:1、
設置音量:1
};
/**
* 枚舉允許的調解器,其中鍵是方法名稱。
*
* @type {對象}
*/
export const allowedMediators = {
玩:1、
暫停:1
};
函數中間件迭代器(方法){
返回(值,mw)=> {
// 如果前一個中間件終止,傳遞終止
如果(值===終止符){
返回終結者;
}
如果(mw[方法]){
返回 mw[方法](值);
}
返回值;
};
}
函數 executeRight(mws,方法,值,終止){
對於(讓 i = mws.length - 1; i >= 0; i--){
const mw = mws[i];
如果(mw[方法]){
mw[方法](終止,價值);
}
}
}
/**
* 清除播放器的中間件緩存。
*
* @param {Player} 播放器
* {@link Player} 實例。
*/
導出函數 clearCacheForPlayer(player) {
middlewareInstances[player.id()] = null;
}
/**
* {
* [播放器 ID]:[[MW 工廠,微型實例],...]
* }
*
* @私人的
*/
函數 getOrCreateFactory(播放器,mwFactory){
const mws = middlewareInstances[player.id()];
讓 mw = null;
如果(mws === 未定義 || mws === null){
mw = mwFactory(玩家);
middlewareInstances[player.id()] = [[mwFactory, mw]];
返回兆瓦;
}
為 (讓我 = 0; 一世 < . 長度; 我 ++) {
const [mwf, mwi] = mws[i];
如果(MWF!== 米工廠){
繼續;
}
分子量 = 分子量;
}
如果(mw === null){
mw = mwFactory(玩家);
mws.push([mwFactory, mw]);
}
返回兆瓦;
}
function setSourceHelper(src = {}, middleware = [], next, player, acc = [], lastRun = false) {
常量 [MW 工廠,... 其他] = 中間件;
// 如果 mwFactory 是一個字符串,那麼我們正處於岔路口
如果(類型 mwFactory === '字符串'){
setSourceHelper(src, middlewares[mwFactory], next, player, acc, lastRun);
// 如果我們有一個 mwFactory,用播放器調用它來獲取 mw,
// 然後調用mw的setSource方法
} 否則如果(mwFactory){
const mw = getOrCreateFactory(播放器, mwFactory);
// 如果 setSource 不存在,隱式選擇這個中間件
如果(!mw.setSource){
acc.push(mw);
返回 setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
mw.setSource(assign({}, src), function(err, _src) {
// 發生了一些事情,嘗試當前級別的下一個中間件
// 確保使用舊的 src
如果(錯誤){
返回 setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
// 我們已經成功了,現在我們需要更深入
acc.push(mw);
// 如果是同一類型,則繼續沿當前鏈向下
// 否則,我們要沿著新鏈向下
setSourceHelper(
_src,
類型 === _src 類型?其中一種:中間件 [_src.type],
下一個,
播放器,
累積,
最後一次
);
});
} else if (mwrest.length) {
setSourceHelper(src, mwrest, next, player, acc, lastRun);
} else if (lastRun) {
下一個(源,acc);
}其他{
setSourceHelper(src, middlewares['*'], next, player, acc, true);
}
}