Vimeo images and javascript



所以我的缩略图系统无法正常工作。它从vimeo获得一个图像,并将其放入。所以我试着让它循环,因为那样看起来更好。

但是我不能让它工作:(有人能帮我吗?

<div class="row">
<div class="col-sm-3"><img src="" id="img1" class="img-rounded" width="100%" height="200px"></img></div>
<div class="col-sm-3"><img src="" id="img2" class="img-rounded" width="100%" height="200px"></img></div>
<div class="col-sm-3"><img src="" id="img3" class="img-rounded" width="100%" height="200px"></img></div>
<div class="col-sm-3"><img src="" id="img4" class="img-rounded" width="100%" height="200px"></img></div>
</div>
<br>
<div class="row">
<div class="col-sm-3"><img src="" id="img5" class="img-rounded" width="100%" height="200px"></img></div>
<div class="col-sm-3"><img src="" id="img6" class="img-rounded" width="100%" height="200px"></img></div>
<div class="col-sm-3"><img src="" id="img7" class="img-rounded" width="100%" height="200px"></img></div>
<div class="col-sm-3"><img src="" id="img8" class="img-rounded" width="100%" height="200px"></img></div>
</div>
</div>
</body>
<script>
var ids = ["169971394", "169657641", "169569693", "169569661", "169569619", "169569539", "169569509", "169566439"]
var imgs= ["img1", "img2", "img3", "img4", "img5", "img6", "img7", "img8"]
for (i = 0; i < 7; i++) {
$(document).ready(function () {
var vimeoVideoUrl = 'https://player.vimeo.com/video/' + ids[i];
console.log(vimeoVideoUrl);
var match = /vimeo.*/(d+)/i.exec(vimeoVideoUrl);
if (match) {
var vimeoVideoID = match[1];
$.getJSON('http://www.vimeo.com/api/v2/video/' + vimeoVideoID + '.json?callback=?', { format: "json" }, function (data) {
featuredImg = data[0].thumbnail_large;
console.log(imgs[i]);
$(imgs[i]).attr("src", featuredImg);
});
}
});
}
</script>

(以上是重要部分。)仅供参考:我使用了bootstrap和jquery。(还有其他一些事情,但这些并不重要)

一些背景

在循环中做这类事情的复杂性在于$.getJSON()异步,而for循环是synchronous。要想对差异有一个基本的了解,请查看这个答案。但总体思路是:

同步:事物按顺序执行。一个操作完成后,下一个操作开始。

示例:

var a = 0; // This is executed first
a = a + 1; // This is executed second

异步同步操作在继续使用脚本之前不等待异步运算完成

示例:

// This is executed first
var a = 0;
// This is executed 2nd, but the function inside won't be called for 1 second
setTimeout(function() {
// this is executed last, outputs 1
console.log(a);
}, 1000);
// this is executed third, before the function call
a = a + 1;

你的问题

在示例代码中,您正在同步操作中执行异步函数。通常情况下,这是可以的,你真的不必担心。当你试图在异步函数中使用变量i,但在同步操作(for循环)期间变量i被更改时,就会出现问题。

以下是显示发生的情况的示例

for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000)
}

思考一下

现在,通过查看代码,您可能会期望它等待1秒,然后将每个号码记录到控制台,类似

-> 0
-> 1
-> 2
-> 3
-> 4

The Catch

但是,如果您实际运行上面的代码段,您会看到它每次都会记录5。这是因为当回调函数实际运行时,变量i的值实际上为5。

但是怎么做呢

如何?for循环在每个setTimout()完成1秒等待之前继续执行。因此,在1秒结束时,循环已经将i增加到破坏循环的点,在本例中为5

在您的问题中,回调函数中的一个简单console.log(i);很可能会显示7八次,因为变量i仍在递增,而$.getJSON()实际上正在等待返回结果。当结果实际返回时,循环可能已经运行完毕,i将等于7

解决方案

为了确保我们将视频和图像按正确的顺序放在页面上,并且我们实际上将每个图像放在了正确的位置,我们需要为这种异步行为做一些繁重的解决方案。我对这段代码进行了注释,让您了解每一行都在做什么。

// dom is ready to be manipulated
$(document).ready(function() {
// create an array of our video ids
var ids = [
"169971394",
"169657641",
"169569693",
"169569661",
"169569619",
"169569539",
"169569509",
"169566439"
];
// initialize an empty array that will eventually hold our videos
var videos = [];
// loop through our array of ids
ids.forEach(function(id, i) {
// because these are in order, ids[0] should be in #img1 etc
var image = '#img' + (i + 1);
// get your video url --not actually used in this code
var vimeoVideoUrl = 'https://player.vimeo.com/video/' + id;
// create an object that holds the information for this video that can
// be gathered *synchronously*
var v = {
id: id,
image: '#img' + (i + 1),
video: vimeoVideoUrl
};
// add this object to our initially empty array
videos.push(v);
/* after the loop ends, videos array might look like this
[
{
id: "169971394",
image: "#img1",
video: "https://player.vimeo.com/video/169971394"
},
{
... next video
} ... for each video
]
*/
// do our ajax operation to get the rest of the video information
$.getJSON(
'https://www.vimeo.com/api/v2/video/' + id + '.json?callback=?', {
format: "json"
},
// REMEMBER -- this function is *asynchronous* and we can't trust the
// value of the increment from our loop, so this is relatively complex
function(data) {
// get the id of the returned video
var id = data[0].id;
// get the thumbnail
var thumb = data[0].thumbnail_large;
// loop through our videos array
videos.forEach(function(v, i) {
// find the element of the array with the id that was just returned
if (v.id == id) {
// and add the thumbnail url to the object
videos[i].thumbnail = thumb;
/* an element of the videos array will look like this when the callback
has finished for that video
{
id: "169971394",
image: "#img1",
video: "https://player.vimeo.com/video/169971394",
thumbnail: "https://i.vimeocdn.com/video/574879586_640.jpg"
}
notice that the thumbnail property is now set
*/
}
});
// each time we execute the callback, we need to know if it's the last 
// execution, so we will need to check if every callback has been completed
// this condition returns false if the thumbnail element is not assigned
// to every object in the videos array, which would tell us that this isn't
// the last execution of the callback
if (videos.every(function(v) {
return v.thumbnail !== undefined
})) {
// if this is the last execution of the callback,
// loop through each item in the videos array
videos.forEach(function(video) {
// set the src of the video's corresponding image to the url of the thumbnail
$(video.image).attr("src", video.thumbnail);
});
}
}
);
});
});

https://jsfiddle.net/o82L6q48/2/在中看到这一点

注意,这可能比实际需要的更复杂,但它是有效的,我希望你能从中学到一些东西

最新更新