Промис не дожидается ответа из асинхронной функции
Я новичок в JS и еще учусь. Решил попробовать написать расширение для Chrome.
Расширение принимает список из ключевых слов и после этого цикл должен формировать из каждого слова ссылку и создавать новую вкладку, затем на этой вкладке он отбирает некоторые эллементы (ссылки) и добавляет их в переменную, далее вкладка закрывается, а потом функция возвращает массив со всеми ссылками для всех ключевых слов.
const linkedInSearchElement = (keyWords) => {
return new Promise((resolve, reject) => {
chrome.tabs.create({
url: `https://www.linkedin.com/sales/search/company?keywords=${keyWords}&page=1&searchSessionId=0ehP5LShQGivgqjzo9LqjQ%3D%3D`
}, (tab) => {
resolve(tab.id);
});
}).then((tabId) => {
return new Promise((resolve, reject) => {
chrome.tabs.executeScript(tabId, {
'code': 'function linksWineSearch (){let wineLinks = []; const wineCompNames = document.getElementsByClassName("result-lockup__name"); for (let wineCycleCount = 0; wineCycleCount <wineCompNames.length; wineCycleCount++) {wineLinks[wineCycleCount] = wineCompNames[0].children[0].href} console.log(wineLinks); return wineLinks; } linksWineSearch(); '
}, (wineLinks) => {
resolve([wineLinks, tabId]);
});
})
}).then((linksAndId) => {
return new Promise((resolve, reject) => {
chrome.tabs.remove(linksAndId[1], () => {
resolve(linksAndId[0]);
});
})
}).catch(error => console.log(error));
};
const linkedInGeneralSearch = (readyNames) => {
const compNames = [...readyNames];
let linkList = [];
for (let i = 0; i < 2; i++) {
const keyWords = compNames[i];
console.log(linkedInSearchElement(keyWords));
const searchElementResult = linkedInSearchElement(keyWords);
linkList = [...searchElementResult];
}
return linkList;
}
Но почему-то после 'chrome.tabs.create' все '.then' пропускаются и функция 'linkedInSearchElement' выполняется заново и так далее. И только после всех итераций по очереди начинают выполнятся все '.then'.
Почему все .then не выполняются по порядку, функция запускается заново до окончания предыдущей?
P.S. Я старался изучить асинхронное программирование в JS, но тут не могу разобраться)) Заранее спасибо за ответы!
Ответы (1 шт):
Все дело в том что асинхронная функция возвращает обещание (Promise) - асинхронный код, который в свою очередь уже имеет свой жизненный цикл, и два статуса завершения работы: "успех" (then) или "провал" (catch).
Далее, тут:
for (let i = 0; i < 2; i++) ты вызываешь синхронный цикл, который запускает 2 раза подряд linkedInSearchElement. То есть ты имеешь: в одном потоке вызвал асинхронную функцию и тут же работаешь с данными, которые вообще не в курсе что там с ними происходит внутри асинхронного блока.
Обязательно прочитай что такое async/await если хочешь дальше учиться писать грамотный асинхронный код.
Идея сделать так:
for (let i = 0; i < 2; i++) {
const keyWords = compNames[i];
const searchElementResult = []
linkList = [...await linkedInSearchElement(keyWords)];
}
То есть ты "ждешь" пока закончится твой асинхронный метод linkedInSearchElement, и берешь его значение и помещаешь в массив.
Но на самом деле, если сделаешь как я написал, это не сработает. Потому что await работает только внутри async (асинхронных функции).
Итоговый вариант должен выглядеть как то так:
async function linkedInSearchElement(keyWords) {
try {
const tabId = await chrome.tabs.create({url: ''};
const linksAndId = await chrome.tabs.executeScript(tabId, { 'code': ''};
chrome.tabs.remove(linksAndId[1]);
return linksAndId[0];
} catch (error) {
console.log(error);
} }
async function linkedInGeneralSearch(readyNames) {
const compNames = [...readyNames];
return await processArray(compNames); }
async function processArray(array) {
const linkList = [];
for (const item of array) {
linkList.concat(await linkedInSearchElement(item));
}
return linkList; }
Код не запускал.