I have created a jQuery script to, from my web page, automate the creation of lists on my YouTube channel. The problem is that the API does not seem to be able to attend to the fifteen video addition requests that I make per list through a each()
; it adds between four and six, and often not in the order it should, so I thought a possible solution would be to add a delay at the end of each cycle of the loop so that the server has time to react to each request.
The script:
$(function()
{
$('.crear-lista-yt').click(function() //Al hacer clic en el botón "Publicar"
{
var idLista = $(this).parent().siblings('.bloque-canciones').attr('id'); //Captura el id de la lista
var nombre = $(this).parent().siblings('.nombre-lista').html(); //Captura el nombre de la lista
var descripcion = $(this).parent().siblings('.descripcion-lista').html(); //Captura la descripción de la lista
var idListaYT; //Variable para almacenar posteriormente el enlace de la lista de YouTube creada
var peticionLista = gapi.client.youtube.playlists.insert( //Se almacenan en la variable los datos (título, descripción y estado) que definen la lista a crear
{
part: 'snippet, status',
resource:
{
snippet:
{
title: nombre,
description: descripcion
},
status: {privacyStatus: 'public'}
}
});
peticionLista.execute(function(respuesta) //Se ejecuta la petición
{
idListaYT = respuesta.result.id; //Se almacena el id de la lista creada
if(idListaYT) //Si se ha creado la lista
{
$(`.cancion-lista-${idLista}`).each(function() //Bucle que recorre todas las canciones del recopilatorio personalizado
{
var idVideoYT = $(this).children().children('.enlace-youtube').data('video'); //Id de YoutTube correspondiente a cada cancion
var detalles = {videoId: idVideoYT, kind: 'youtube#video'} //Se almacena el id del vídeo y que es un vídeo de YouTube
var peticionCancion = gapi.client.youtube.playlistItems.insert( //De manera similar a como se hace con la lista, en esta variable se almacenan los datos de cada vídeo
{
part: 'snippet',
resource:
{
snippet:
{
playlistId: idListaYT, //El id de la lista a la que se añade el vídeo
resourceId: detalles //Los datos de cada vídeo
}
}
});
peticionCancion.execute(function(respuesta) //Se ejecuta la petición
{
if(respuesta.result)
{
console.log(respuesta.result.snippet.title);
}
else
{
console.log('No se ha agregado el vídeo')
}
});
setTimeout(function(){ console.log('Han pasado 1000 ms'); }, 1000);
});
}
else swal('Ups...', 'Algo ha fallado; intenta crear tu lista de YouTube más tarde...', 'error', {button: false}); //Si no, da un mensaje de error
});
});
});
Well, needless to say, it setTimeout(function(){ console.log('Han pasado 1000 ms'); }, 1000)
's not working for me; an example of what the console shows:
On this occasion he has been able to add only five of the fifteen videos - those for which it is made console.log(respuesta.result.snippet.title);
- and my attempts to delay all appear at the end:
Obviously the process did not last at least 15,000 ms, the information appeared immediately on the console.
What could I do?
I don't have score to leave a comment, but I hope to be useful.
In most of the google apis that I have been able to use, all the insertion operations are done first and then they are all executed together at the end. From what I could understand from your code, you are inserting, executing, looping.
tries to loop only the inserts and finally does the execution.
If my answer is not correct, let me know so I delete it, greetings.
I would say that the problem is that you are launching too many requests in parallel, and given that you want them to remain in the order you have defined, perhaps it is best to serialize the requests, that is, let one go until the previous one has been completed.
To achieve this without having to change all the logic of your script, you can make an array with the requests to execute and fire the next request, if any, until the first one finishes.
To do this, it would be necessary to factor the code of the function that is executed on completion of each request into a separate function, say
alFinalizarPeticion
. This function, in addition to printing the messages, will be responsible for launching the next request. The routine that launches the next request, in turn, delivers the reference toalFinalizarPeticion
to be called when finished and thus repeat the operation until all requests are finished, for example by this code:Now, then, we would have to adjust the original code so that it places the requests in the array and, in the end, launches the first request, something like:
If you still want to risk sending multiple requests in parallel, and just space them out in time, you can use a similar infrastructure, only instead of firing the next one until a request finishes, fire it with a timer. So, re-writing the first part:
To start the executions, then, the timer would have to be set. I am using an interval type timer so that it runs automatically several times, until the task is completed. To start the chain , you would have to call
setInterval()
, as follows:I've placed a call to
ejecutarSiguientePeticion()
right aftersetInterval()
so as not to wait a second before the first request is fired. This line could be removed if waiting is necessary or acceptable.This will fire a request every second until the ones in the array are complete.
NOTE: The code could contain syntax errors, I have written it here and, since you do not publish a minimum and verifiable example , it is not easy for me to test it. I hope that if you understand the solution with the explanation I have given you, you will be able to correct any details that I may have missed.