v2.5.2
Giriş yap

Node forEach döngüsünü kırmak

kadircm
364 defa görüntülendi

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)
	})
	
})
Cevap yaz
Cevaplar (1)
ebykdrms
805 gün önce

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")
    );
}