/**
* @file 미들웨어.js
* @module 미들웨어
*/
import { assign } from '../utils/obj.js';
'../utils/string-cases.js'에서 {toTitleCase} 가져오기;
const 미들웨어 = {};
const middlewareInstances = {};
내보내기 const TERMINATOR = {};
/**
* 미들웨어 객체는 다음과 같은 메서드가 있는 일반 JavaScript 객체입니다.
* 허용 목록에 있는 {@link Tech} 방법과 일치
* {@link module:middleware.allowedGetters|getters},
* {@link module:middleware.allowedSetters|세터}, 그리고
* {@link module:middleware.allowedMediators|중재자}.
*
* @typedef {객체} MiddlewareObject
*/
/**
* 다음을 반환해야 하는 미들웨어 팩토리 함수
* {@link module:middleware~MiddlewareObject|미들웨어객체}.
*
* 이 공장은 필요할 때 각 플레이어에 대해 플레이어와 함께 호출됩니다.
* 인수로 전달되었습니다.
*
* @callback 미들웨어팩토리
* @param {플레이어} 플레이어
* Video.js 플레이어.
*/
/**
* 플레이어가 팩토리 함수를 통해 사용해야 하는 미들웨어 정의
* 미들웨어 객체를 반환합니다.
*
* @param {문자열} 유형
* 일치시킬 MIME 유형 또는 모든 MIME 유형의 경우 `"*"`.
*
* @param {MiddlewareFactory} 미들웨어
* 실행될 미들웨어 팩토리 기능
* 일치 유형.
*/
내보내기 기능 사용(유형, 미들웨어) {
미들웨어[유형] = 미들웨어[유형] || [];
미들웨어[유형].push(미들웨어);
}
/**
* 유형별 미들웨어(또는 모든 미들웨어)를 가져옵니다.
*
* @param {문자열} 유형
* 일치시킬 MIME 유형 또는 모든 MIME 유형의 경우 `"*"`.
*
* @return {함수[]|정의되지 않음}
* 미들웨어의 배열 또는 존재하지 않는 경우 '정의되지 않음'.
*/
내보내기 기능 getMiddleware(유형) {
경우 (유형) {
return 미들웨어[유형];
}
미들웨어 반환;
}
/**
* 미들웨어를 사용하여 비동기적으로 소스를 설정합니다.
* 미들웨어를 일치시키고 각각에 `setSource`를 호출하여
* 매번 이전에 반환된 값.
*
* @param {플레이어} 플레이어
* {@link Player} 인스턴스.
*
* @param {Tech~SourceObject} src
* 소스 객체.
*
* @param {함수}
* 실행할 다음 미들웨어.
*/
내보내기 기능 setSource(플레이어, src, 다음) {
player.setTimeout(() => setSourceHelper(src, 미들웨어[src.type], 다음, 플레이어), 1);
}
/**
* 기술이 설정되면 각 미들웨어의 `setTech` 메소드에 기술을 전달합니다.
*
* @param {Object[]} 미들웨어
* 미들웨어 인스턴스의 배열.
*
* @param {기술} 기술
* Video.js 기술.
*/
내보내기 기능 setTech(middleware, tech) {
미들웨어.forEach((mw) => mw.setTech && mw.setTech(기술));
}
/**
* 각 미들웨어를 통해 먼저 기술에서 getter를 호출합니다.
* 플레이어의 오른쪽에서 왼쪽으로.
*
* @param {Object[]} 미들웨어
* 미들웨어 인스턴스의 배열.
*
* @param {기술} 기술
* 현재 기술.
*
* @param {문자열} 메서드
* 메서드 이름.
*
* @return {혼합}
* 미들웨어가 가로챈 후 기술의 최종 값입니다.
*/
내보내기 기능 get(middleware, tech, method) {
return middleware.reduceRight(middlewareIterator(방법), 기술[방법]());
}
/**
* 플레이어에게 주어진 인수를 취하고 각각의 setter 메서드를 호출합니다.
* 미들웨어는 왼쪽에서 오른쪽으로 기술입니다.
*
* @param {Object[]} 미들웨어
* 미들웨어 인스턴스의 배열.
*
* @param {기술} 기술
* 현재 기술.
*
* @param {문자열} 메서드
* 메서드 이름.
*
* @param {혼합} arg
* 기술에 설정할 값입니다.
*
* @return {혼합}
* `tech`의 `method` 반환 값.
*/
내보내기 기능 세트(미들웨어, 기술, 방법, arg) {
return tech[method](middleware.reduce(middlewareIterator(method), arg));
}
/**
* 플레이어에게 주어진 인수를 받아서 `call` 버전의
* 왼쪽에서 오른쪽으로 각 미들웨어의 메소드.
*
* 그런 다음 기술에서 전달된 메서드를 호출하고 변경되지 않은 결과를 반환합니다.
* 이번에는 오른쪽에서 왼쪽으로 미들웨어를 통해 플레이어로 돌아갑니다.
*
* @param {Object[]} 미들웨어
* 미들웨어 인스턴스의 배열.
*
* @param {기술} 기술
* 현재 기술.
*
* @param {문자열} 메서드
* 메서드 이름.
*
* @param {혼합} arg
* 기술에 설정할 값입니다.
*
* @return {혼합}
* `tech`의 `method` 반환 값은
* 미들웨어의 반환 값.
*/
내보내기 기능 mediate(middleware, tech, method, arg = null) {
const callMethod = '호출' + toTitleCase(방법);
const middlewareValue = 미들웨어.리듀스(middlewareIterator(callMethod), arg);
const 종료됨 = middlewareValue === TERMINATOR;
// 사용되지 않습니다. `null` 반환 값은 대신 TERMINATOR를 반환해야 합니다.
// techs 메서드가 실제로 null을 반환하는 경우 혼동을 방지합니다.
const returnValue = 종료됨 ? null : 기술[방법](middlewareValue);
executeRight(미들웨어, 메소드, returnValue, 종료됨);
반환 값 반환;
}
/**
* 키가 메서드 이름인 허용된 게터의 열거.
*
* @type {객체}
*/
내보내기 const allowedGetters = {
버퍼링됨: 1,
현재 시간: 1,
지속: 1,
음소거: 1,
재생: 1,
일시중지: 1,
검색 가능: 1,
용량: 1,
종료: 1
};
/**
* 키가 메소드 이름인 허용된 세터의 열거.
*
* @type {객체}
*/
내보내기 const allowedSetters = {
setCurrentTime: 1,
음소거 설정: 1,
볼륨 설정: 1
};
/**
* 키가 메소드 이름인 허용된 중재자의 열거.
*
* @type {객체}
*/
내보내기 const allowedMediators = {
놀다: 1,
정지시키다: 1
};
함수 middlewareIterator(방법) {
반환 (값, mw) => {
// 이전 미들웨어가 종료된 경우 종료를 전달합니다.
if (값 === 종결자) {
반환 터미네이터;
}
if (mw[방법]) {
return mw[방법](값);
}
반환 값;
};
}
function executeRight(mws, 메서드, 값, 종료됨) {
for (let i = mws.length - 1; i > = 0; 나--) {
const mw = mws[i];
if (mw[방법]) {
mw[방법](종료, 값);
}
}
}
/**
* 플레이어의 미들웨어 캐시를 지웁니다.
*
* @param {플레이어} 플레이어
* {@link Player} 인스턴스.
*/
내보내기 기능 clearCacheForPlayer(player) {
middlewareInstances[player.id()] = null;
}
/**
* {
* [playerId]: [[mwFactory, mwInstance], ...]
* }
*
* @사적인
*/
함수 getOrCreateFactory(플레이어, mwFactory) {
const mws = 미들웨어 인스턴스[player.id()];
mw = null로 하자;
if (mws === 정의되지 않음 || mws === null) {
mw = mwFactory(플레이어);
middlewareInstances[player.id()] = [[mwFactory, mw]];
반환 mw;
}
에 대한 (하자 i = 0; i < mws.길이; i++) {
const [mwf, mwi] = mws[i];
if (mwf !== mwFactory) {
계속하다;
}
mw = mwi;
}
경우 (mw === null) {
mw = mwFactory(플레이어);
mws.push([mwFactory, mw]);
}
반환 mw;
}
function setSourceHelper(src = {}, 미들웨어 = [], 다음, 플레이어, acc = [], lastRun = false) {
const [mwFactory, ...mwrest] = 미들웨어;
// mwFactory가 문자열이면 갈림길에 있는 것입니다.
if (mwFactory 유형 === '문자열') {
setSourceHelper(src, 미들웨어[mwFactory], 다음, 플레이어, acc, lastRun);
// mwFactory가 있으면 플레이어와 함께 호출하여 mw를 얻습니다.
// 그런 다음 mw의 setSource 메서드를 호출합니다.
} 그렇지 않으면 (mwFactory) {
const mw = getOrCreateFactory(player, mwFactory);
// setSource가 없으면 암시적으로 이 미들웨어를 선택합니다.
if (!mw.setSource) {
acc.push(mw);
return setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
mw.setSource(assign({}, src), function(err, _src) {
// 문제 발생, 현재 레벨에서 다음 미들웨어 시도
// 이전 src를 사용해야 합니다.
경우 (오류) {
return setSourceHelper(src, mwrest, next, player, acc, lastRun);
}
// 성공했습니다. 이제 더 깊이 들어가야 합니다.
acc.push(mw);
// 같은 유형이면 현재 체인을 계속 진행합니다.
// 그렇지 않으면 새 체인으로 내려가고 싶습니다.
setSourceHelper(
_src,
src.type === _src.type ? mwrest : 미들웨어[_src.type],
다음,
플레이어,
예,
lastRun
);
});
} 그렇지 않으면 (mwrest.length) {
setSourceHelper(src, mwrest, next, 플레이어, acc, lastRun);
} 그렇지 않으면 (마지막 실행) {
다음(src, acc);
} else {
setSourceHelper(src, middlewares['*'], next, player, acc, true);
}
}