Моя цель — получить метаданные о видео из Brightcove CMS. API путем передачи идентификаторов видео.
Метаданные наших видео хранятся в четырех разных бизнес-подразделениях (или профилях), поэтому я должен запрашивать конечную точку каждого бизнес-подразделения отдельно. Я не знаю, какой идентификатор видео будет найден в каком бизнес-подразделении. Я могу отправить максимум 10 идентификаторов видео за вызов. Ниже приведены шаги, необходимые для получения метаданных видео по идентификатору видео.
1) Получите доступ token
(на этом шаге используются учетные данные клиента, которые я предоставляю).
2) Передать доступ token
к объекту запроса (sendRequest
) через параметр options
.
3) Разобрать ответ и поместить его в глобальный videosArray
.
4) Повторите шаги с 1 по 3 для каждого набора из 10 или менее уникальных идентификаторов видео (представленных многомерным массивом).
5) Повторите шаги с 1 по 4 для каждой учетной записи видео (подразделения).
К вашему сведению: шаблонный код от Brightcove использует обратные вызовы. Я преобразовал этот код в async/await. Возможно, кто-то также может предложить улучшения моего кода async/await, если он неверен.
Я использую модули Node 8.10, ES6+ и request-promise-native (среди прочего). Любые переменные, которые кажутся неявно объявленными, объявляются в глобальной области видимости. Я просто не вставил их сюда.
bizUnit — это массив объектов как таковых (всего у меня есть четыре разных бизнес-единицы для перебора):
businessUnits = [
bizUnitOne: {
account_id: 'uhdafoia98243r2',
client_id: 'oidahf982y229hr',
client_secret: 'iuahf9o4398oyg',
player_url: 'afdhy984wyyfsg',
},
bizUnitTwo: {
account_id: 'uhdafoia98243r2',
client_id: 'oidahf982y229hr',
client_secret: 'iuahf9o4398oyg',
player_url: 'afdhy984wyyfsg',
}
]
Получить объявление функции токена доступа:
async function getAccessToken(bizUnit) {
// base64 encode the client_id:client_secret string for basic auth
let bodyObj,
token;
authString = new Buffer(bizUnit.client_id + ':' + bizUnit.client_secret).toString('base64');
let payLoad = {
method: 'POST',
url: 'https://oauth.brightcove.com/v3/access_token?grant_type=client_credentials',
headers: {
'Authorization': 'Basic ' + authString,
'Content-Type': 'application/json'
},
json: true
};
try {
let result = await request(payLoad);
bodyObj = await JSON.parse(result);
token = bodyObj.access_token;
return token;
}
catch (error) {
console.log(oauthError, error);
}
}
Отправить заявление запроса:
async function sendRequest(options) {
let requestOptions = {
method: 'GET',
url: options.url,
headers: {
'Authorization': 'Bearer ' + options.token,
'Content-Type': 'application/json'
},
json: true
};
let makeRequest = async (reqOptions) => {
try {
let body = await request(reqOptions);
return JSON.parse(body);
} catch (error) {
console.log(apiError, error);
}
};
// make the request
await makeRequest(requestOptions);
}
Пример массива идентификаторов видео (теоретически этот массив может содержать сотни или тысячи идентификаторов видео в блоках по 10 или меньше):
videoIdsGroup = [ [53245,2352,243252,2352352,234234,234324,2342342,24242,23542,234324], [43534, 34543, 3453, 3453345] ];
Собираем все вместе и делаем запрос:
function setUpVideoRequest(bizUnit) {
(async (bu) => {
// note that access tokens live for 5 minutes
// but you can always request one for each call to be safe
for (let videoIdsArr of videoIdsGroup) {
let endPoint,
videoIdsString = videoIdsArr.join();
endPoint = '/accounts/' + bu.account_id + '/videos/' + videoIdsString + '&sort=' + sort;
options.url = baseURL + endPoint;
options.token = await getAccessToken(bizUnit);
const videos = await sendRequest(options);
videosArray = videosArray.concat(videos);
}
})(bizUnit);
}
Начало выполнения:
for (let bu of businessUnits) {
/*the counter below is to reveal how many times and in what sequence this for...of loop is executing. my console.log indicates that this loop iterates through all businessUnits immediately, but then it runs again and eventually succeeds in some of the calls and repeats those calls even though it already got data.*/
let parentCounter = 0;
console.log("BizUnit COUNTER", parentCounter++);
try {
promises.push(setUpVideoRequest(bu));
} catch (error) {
throw error;
}
}
Сообщение об ошибке, которое я получаю (это повторяется, а затем я время от времени получаю некоторые данные, а затем ошибка повторяется снова):
statusCode: 400,
message: '400 - {"error":"invalid_client","error_description":"The "client_id" parameter is missing, does not name a client registration that is applicable for the requested call, or is not properly authenticated."}',
Я знаю, что циклы for...of работают неправильно, но я пробовал обычный цикл for с итератором [i], я также пробовал for...in и forEach. Ни один из них не работает корректно.
Я просто хочу иметь возможность сделать запрос для каждого идентификатора учетной записи (бизнес-подразделения) и для каждого массива видео, получить все метаданные видео и поместить их в глобальный videosArray
примерно так:
Promise.all(promises).then((results) => {
promiseVidArray.push(results);
});
Заранее спасибо за вашу помощь и понимание.
await
, вы должны иметь обещание и не использовать API обратного вызоваrequest
. Если вы уже используетеrequest-promise-*
, просто не передавайте обратный вызов! Посмотрите его документацию. - person Bergi   schedule 17.09.2018async function
приниматьcallback
. Вы должны простоawait
выполнять асинхронные действия, а затемreturn
. - person Bergi   schedule 17.09.2018async
/await´ yet, try using promises without any syntactic sugar, i.e. use
.then()` - person Bergi   schedule 17.09.2018