Yeni bir Promise () yapıcısının içinde zaman uyumsuz / beklemeyi kullanmak bir anti-model mi?


93

async.eachLimitBir seferde maksimum işlem sayısını kontrol etmek için işlevi kullanıyorum .

const { eachLimit } = require("async");

function myFunction() {
 return new Promise(async (resolve, reject) => {
   eachLimit((await getAsyncArray), 500, (item, callback) => {
     // do other things that use native promises.
   }, (error) => {
     if (error) return reject(error);
     // resolve here passing the next value.
   });
 });
}

Gördüğünüz gibi, myFunctionişlevi eşzamansız olarak bildiremiyorum çünkü işlevin ikinci geri çağrısının içindeki değere erişimim yok eachLimit.


"Gördüğünüz gibi, myFunction'ı eşzamansız olarak bildiremiyorum" --- daha fazla ayrıntı verebilir misiniz?
zerkms

1
Tamam özür dilerim. Yapıcıya ihtiyacım var çünkü bir seferde 500'den fazla zaman uyumsuz işlemi önlemek için async.eachLimit'e ihtiyacım var. Metin dosyalarından veri indiriyor ve çıkarıyorum ve çok fazla eşzamansız işlemden kaçınmak istiyorum, veriyi çıkardıktan sonra, verilerle bir Promise döndürmeliyim ve onu async.eachLimit'in geri aramasından geri döndüremeyeceğim. .

1. Beklemeye neden ihtiyacınız var? Zaman uyumsuz zaten bir kontrol akışı mekanizmasıdır. 2. node.js içinde vaatlerle async.js kullanmak istiyorsanız, async-q
slebetman

Geri arama cehenneminden kaçınmak için ve eğer bir şey olursa, dış sözler tutulur.

Yanıtlar:


81

Promise yapıcı yürütme işlevi içinde vaatleri etkili bir şekilde kullanıyorsunuz, bu nedenle bu Promise kurucusu anti-modeldir .

Kodunuz ana riske iyi bir örnektir: tüm hataları güvenli bir şekilde yaymamak. Neden orada okuyun .

Ek olarak, async/ kullanımı awaitaynı tuzakları daha da şaşırtıcı hale getirebilir. Karşılaştırmak:

let p = new Promise(resolve => {
  ""(); // TypeError
  resolve();
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.

naif (yanlış) bir asynceşdeğerle:

let p = new Promise(async resolve => {
  ""(); // TypeError
  resolve();
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!

Sonuncusu için tarayıcınızın web konsoluna bakın.

İlki işe yarıyor çünkü bir Promise yapıcı yürütme işlevindeki herhangi bir acil istisna, yeni oluşturulan vaadi uygun bir şekilde reddediyor (ancak .thenkendi başınasın.

İkincisi çalışmaz çünkü bir asyncişlevdeki herhangi bir acil istisna , asyncişlevin kendisi tarafından döndürülen örtük vaadi reddeder .

Bir promise yapıcı çalıştırıcı işlevinin dönüş değeri kullanılmadığından, bu kötü bir haber!

Senin kodun

Tanımlamak için hiçbir sebep yok myFunctionolarak async:

async function myFunction() {
  let array = await getAsyncArray();
  return new Promise((resolve, reject) => {
    eachLimit(array, 500, (item, callback) => {
      // do other things that use native promises.
    }, error => {
      if (error) return reject(error);
      // resolve here passing the next value.
    });
  });
}

Yine de varken neden güncel olmayan eşzamanlılık kontrol kitaplıkları kullanasınız await?


12
İhtiyacınız yok return await: return new Promiseyeterli.
lonesomeday

2
Bu yanıtı resmen onaylıyorum, tamamen aynı şeyi söylerdim :-)
Bergi

1
@celoxxx Buraya bir göz atın . Async.js'yi vaatlerle asla kullanmamalısınız
Bergi

1
@celoxxx Sadece türleri bırakın ve düz js olur. Async.js'yi kullanmamalısınız çünkü farklı arayüzler - düğüm tarzı geri aramalar vs vaatler - çok fazla sürtüşmeye neden olur ve gereksiz karmaşık ve hataya açık koda yol açar.
Bergi

1
Size katılıyorum ... Ama bu kod eski ve olayları + async.js'yi kullanmak için yeniden düzenleme yapıyorum (eşzamansız sınırını kontrol etmek için, henüz. Daha iyi bir yol biliyorsanız, lütfen söyleyin).

16

Yukarıda verilen cevaplara katılıyorum ve yine de, bazen sözünüzde eşzamansız olması daha iyi, özellikle de birkaç işlemi zincirlemek ve sözlere karşılık vermek ve then().then()cehennemden kaçınmak istiyorsanız . Bu durumda şuna benzer bir şey kullanmayı düşünürdüm:

const operation1 = Promise.resolve(5)
const operation2 = Promise.resolve(15)
const publishResult = () => Promise.reject(`Can't publish`)

let p = new Promise((resolve, reject) => {
  (async () => {
    try {
      const op1 = await operation1;
      const op2 = await operation2;

      if (op2 == null) {
         throw new Error('Validation error');
      }

      const res = op1 + op2;
      const result = await publishResult(res);
      resolve(result)
    } catch (err) {
      reject(err)
    }
  })()
});

(async () => {
  await p;
})().catch(e => console.log("Caught: " + e));
  1. PromiseYapıcıya iletilen işlev eşzamansız değildir, bu nedenle linterler hataları göstermez.
  2. Eşzamansız işlevlerin tümü, kullanılarak sıralı olarak çağrılabilir await.
  3. Eşzamansız işlemlerin sonuçlarını doğrulamak için özel hatalar eklenebilir
  4. Hata eninde sonunda güzelce yakalanır.

Yine de bir dezavantajı, try/catchonu takıp taktığınızı hatırlamanız gerektiğidir reject.


4
static getPosts(){
    return new Promise( (resolve, reject) =>{
        try {
            const res =  axios.get(url);
            const data = res.data;
            resolve(
                data.map(post => ({
                    ...post,
                    createdAt: new Date(post.createdAt)
                }))
            )
        } catch (err) {
            reject(err);                
        }
    })
}

kaldırın await ve async bu sorunu çözecektir. Çünkü Promise nesnesini uyguladınız, bu kadar yeter.


Öyleyse örneğinizde, axios.get(url)sanki adı verildiği gibi işlev görecek await axios.get(url)mi?
PrestonDocks
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.