Node forEach döngüsünü kırmak
Bir proxy listem var listemi forEach ile döngüye alıp kaynağını almak istediğim siteye istek gönderiyorum herhangi bir proxy geçerli response verirse döngüyü kırıp içeriği express ile ekrana yazmak istiyorum.
Aşağıdaki kod çalışıyor ancak response aldığım halde döngü devam ediyor kaynağı aldıktan sonra döngünün durmasını nasıl sağlayabilirim ?
const arrow = async (proxy) => {
return new Promise(function(resolve, reject) {
var agent = new HttpsProxyAgent('http://'+proxy)
var proxyRequest = request.defaults({
agent: agent,
timeout: 5000,
headers: {
'user-agent': 'xxxxx'
}
})
proxyRequest.get("link", async function (error, response, body) {
if(!error) {
if(response.body.includes("Your file is ready")) {
console.log(`${proxy} => Success`)
resolve(body)
}
}
})
})
}
async function getData(data) {
return new Promise( async function(resolve, reject) {
data.forEach(async proxy => {
let content = await arrow(proxy)
if(content.includes("Your file is ready")) {
resolve(content)
}
})
})
}
app.get("/get", (req, res) => {
let proxies = fs.readFileSync("proxies.txt", {encoding:'utf8', flag:'r'}).split(/\r?\n/)
getData(proxies).then(subContent => {
res.send(subContent)
})
})
stackoverflow'da sizinkine benzer bir soru sorulmuş. Kendimce biraz yorum ekleyerek paylaşıyorum:
Array.forEach döngüsünü break çağırır gibi nasıl sonlandırabilirim?
[1,2,3].forEach(function(el) {
if(el === 1) break;
});
Bunu forEach
fonksiyonunda nasıl yapabilirim? Ben return;
, return:false;
ve break
denedim... Ama break
patlıyor ve return
de döngüyü sonlandırmıyor.
Doğru Cevap:
forEach
içinde break
ile döngüyü sonlandırma özelliği yok. Eğer for
kullanamıyorsanız, ille de forEach
kullanacaksanız try-catch
içinde bir exception fırlatabilirsiniz.
var breakData = {};
try {
[1, 2, 3].forEach(function(el) {
if (el === 2) {
breakData.data = el; // bulduğumuz veriyi breakData objesine aktaralım.
throw breakData; // Objeyi exception (istisna) olarak fırlatalım.
}
});
}
catch (e) {
// Buraya gelindiyse ya throw breakData komutu çalışmıştır ya da başka bir hata oluşmuştur.
// Eğer oluşan exception'da data değeri yoksa bizim oluşturduğumuz hata dışında bir hata oluşmuşsa bunu da görelim.
if(!e.data) console.error(e);
}
// Döngü sonucu oluşan verimiz breakData objesindeki data key'inde.
console.log(breakData.data);
NOT: Kodlarda yaptığım değişikliği test etmedim. Sorun yaşarsanız direkt stackoverflow'daki örneği inceleyebilirsiniz.
Kaynak: https://stackoverflow.com/questions/2641347/short-circuit-array-foreach-like-calling-break
Sizin sorunuza gelecek olursak kodunuzu şu şekilde düzenleyebilirsiniz:
async function getData(data) {
try {
data.forEach(async proxy => {
const content = await arrow(proxy);
if(content.includes("Your file is ready")) {
throw { success: content };
}
});
}
catch(e) {
if(!e.success) {
console.error("Hata oluştu", e);
return false;
}
return e.success;
}
return undefined;
}
Ama bence forEach yerine doğrudan for kullanın.
Böylece throw
veya break
kullanmak zorunda kalmazsınız.
async function getData(data) {
for(let i = 0; i < data.length; i++) {
const proxy = data[i];
const content = await arrow(proxy);
if(content.includes("Your file is ready")) return content;
}
return null;
}
Veya döngü yerine Array.find kullanın. find, bulduğu ilk elemanı döndürür. Bulamazsa undefined döner.
find içinde hiç async fonksiyon kullanmamıştım ama denemek lazım...
async function getData(data) {
return data.find(
async (proxy) => (await arrow(proxy)).includes("Your file is ready")
);
}