在电子商务网站中,用户可以通过鼠标或手势交互实现 360 度全方位查看产品,提升用户体验。现在需要你设计一个
Pipeline
管道函数,用于控制 360 度展示产品的动画序列,通过管道连接各个动画步骤,使产品以流畅的方式呈现给用户。
本题已经内置了初始代码,打开实验环境,目录结构如下:
├── css
├── effect.gif
├── js
│ ├── index.js
│ └── utils.js
└── index.html
其中:
css
是样式文件夹。index.html
是主页面。js/index.js
是动画序列代码的 js 文件。js/utils.js
是待补充代码的 js 文件。effect.gif
是页面最终的效果图。在浏览器中预览 index.html
页面效果如下:
请在 js/utils.js
文件中的 TODO 部分,实现以下目标:
封装一个支持异步的 pipeline
管道函数,能够按顺序执行一系列异步操作,每个异步操作的结果将作为下一个异步操作的输入。
函数参数说明:
initialValue
:管道的初始值(即 sequence
中第一个函数的参数)。它是整个异步管道的起点。第一个异步步骤将以此值开始,并且后续步骤将在前一步骤的输出基础上进行。sequence
:是一个由具有返回值和可以传参的函数组成的数组,函数可以是普通函数也可以是 Promise 函数。每个函数接收前一个步骤的输出(即该函数的参数是上一个函数的执行结果),并返回一个 Promise。这个数组定义了整个管道中的处理步骤和它们的顺序。函数返回值说明:
pipeline
函数返回一个 Promise
,这个 Promise
最终解析为整个管道执行完成后的结果。测试用例如下:
请注意以下用例仅供参考,实际判题时会修改测试用例,请保证代码的通用性。
sequence
中都为普通函数function fn1(data){
return data +'2.开始左转'
}
function fn2(data){
return data+'3.开始右转'
}
pipeline('1.动画开始',[fn1, fn2]).then(res => {
console.log(res)
})
// 打印结果为:'1.动画开始2.开始左转3.开始右转'
sequence
中都为 promise
函数function fn1(data){
return new Promise(resolve => {
resolve(data+'->执行第一个动画')
})
}
function fn2(data){
return new Promise(resolve => {
resolve(data+'->执行第二个动画')
})
}
pipeline('动画开始',[fn1, fn2]).then(res => {
console.log(res)
})
// 打印结果为:'动画开始->执行第一个动画->执行第二个动画'
完成后,点击屏幕触发动画序列,最终效果可参考文件夹下面的 gif 图,图片名称为 effect.gif
(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。
js/utils.js
文件外的任何内容。pipeline
函数功能进行检测,请保证函数的通用性,不能仅对测试数据有效。sequence
参数都为普通函数且满足需求正确输出,得 5 分。sequence
参数都为 promise
函数且满足需求正确输出,得 5 分。//utils.js
/**
* @param {*} initialValue 初始值
* @param {Array} sequence 由普通函数或 Promise 函数组成的数组
* @return {Promise}
*/
const pipeline = (initialValue, sequence) => {
// TODO: 待补充代码
let promise = Promise.resolve(initialValue);
for(let func of sequence){
promise = promise.then(result=>{
return func(result);
})
}
return promise;
};
// 检测需要,请勿删除
try {
module.exports = { pipeline };
} catch { }
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>产品360度展示</title>
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<h1>产品展示</h1>
<p class="tip">点击屏幕,360度产品展示</p>
<div class="computer">
<div class="inner">
<div class="screen">
<div class="face-one">
<div class="camera"></div>
<div class="display">
<div class="shade">
<div class="computer-screen">
<div class="loading-bar"></div>
<div class="loading-text">正在启动...</div>
</div>
</div>
</div>
<span>蓝桥云课</span>
</div>
<title>Layer 1</title>
</div>
<div class="computerbody">
<div class="face-one">
<div class="touchpad">
</div>
<div class="keyboard">
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key space"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
<div class="key f"></div>
</div>
</div>
<div class="pad one"></div>
<div class="pad two"></div>
<div class="pad three"></div>
<div class="pad four"></div>
</div>
</div>
<div class="shadow"></div>
</div>
<script src="./js/utils.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
1. 头部信息:
<!DOCTYPE html>
:声明文档类型为 HTML5。<meta charset="UTF-8">
:设置字符编码为 UTF - 8。<meta name="viewport" content="width=device-width, initial-scale=1.0">
:使页面在不同设备上正确显示,宽度适应设备宽度,初始缩放比例为 1。<title>产品360度展示</title>
:设置页面标题。<link rel="stylesheet" href="./css/style.css">
:引入外部 CSS 文件。2. 主体内容:
<h1>产品展示</h1>
:显示页面主标题。<p class="tip">点击屏幕,360度产品展示</p>
:显示提示信息,告知用户点击屏幕触发展示。<div class="computer">
:电脑模型的容器,包含屏幕、机身等部分。 <div class="inner">
:内部容器,用于 3D 变换。 <div class="screen">
:电脑屏幕部分,包含摄像头、显示屏等。 <div class="computer-screen">
:电脑屏幕内部区域,包含加载条和加载文字。<div class="computerbody">
:电脑机身部分,包含触摸板、键盘等。<div class="shadow">
:电脑的阴影效果。3. 脚本引入:
<script src="./js/utils.js"></script>
和 <script src="./js/index.js"></script>
:引入外部 JavaScript 文件。.tip{
position: fixed;
bottom: 5px;
left: 0;
font-size: 16px;
width: 100%;
text-align: center;
}
.computer {
width: 150px;
height: 96px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%) scale(2);
perspective: 500px;
}
/* 其他样式规则 */
1. 提示信息样式:
.tip
:提示信息的样式,固定在屏幕底部中央,字体大小为 16px。2. 电脑模型样式:
.computer
:电脑模型的容器样式,设置宽度、高度、位置、缩放比例和透视效果。.shadow
:电脑阴影的样式,设置位置、大小和阴影效果。.screen
和 .computerbody
:分别设置电脑屏幕和机身的样式,包括背景、边框、3D 变换等。.loading-bar
和 .loading-text
:加载条和加载文字的样式,使用动画实现加载效果。@keyframes
动画,如 loading
实现加载条的增长,fade - in
实现加载文字的淡入效果,hide - loading - bar
实现加载条的隐藏动画。/**
* @param {*} initialValue 初始值
* @param {Array} sequence 由普通函数或 Promise 函数组成的数组
* @return {Promise}
*/
const pipeline = (initialValue, sequence) => {
let promise = Promise.resolve(initialValue);
for(let func of sequence){
promise = promise.then(result=>{
return func(result);
})
}
return promise;
};
// 检测需要,请勿删除
try {
module.exports = { pipeline };
} catch { }
1. pipeline
函数:
initialValue
为初始值,sequence
是一个由普通函数或 Promise 函数组成的数组。Promise.resolve(initialValue)
将初始值包装成一个已解决的 Promise。for...of
循环遍历 sequence
数组,使用 then
方法将每个函数依次应用到前一个 Promise 的结果上,确保函数按顺序执行。2. 模块导出:
try { module.exports = { pipeline }; } catch { }
:尝试将 pipeline
函数导出为一个模块,可能用于测试或其他模块引用。四、工作流程▶️ 1. 页面加载:
pipeline
函数。2. 用户交互(点击屏幕):
js/index.js
文件中会监听点击事件。pipeline
函数按顺序执行这些操作。3. 异步操作执行:
pipeline
函数按顺序执行。每个异步操作的结果会作为下一个异步操作的输入,最终完成整个展示流程。