Maison  >  Article  >  interface Web  >  Explication détaillée de l'itérateur asynchrone Node.js et comment l'utiliser

Explication détaillée de l'itérateur asynchrone Node.js et comment l'utiliser

青灯夜游
青灯夜游avant
2021-03-23 10:09:171818parcourir

Cet article vous présentera les itérateurs asynchrones dans Node.js. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.

Explication détaillée de l'itérateur asynchrone Node.js et comment l'utiliser

Les itérateurs asynchrones sont disponibles dans Node depuis la version 10.0.0. Dans cet article, nous aborderons le rôle des itérateurs asynchrones et comment ils peuvent être utilisés où.

Qu'est-ce qu'un itérateur asynchrone ?

Les itérateurs asynchrones sont en fait des versions asynchrones des itérateurs précédents. Les itérateurs asynchrones peuvent être utilisés lorsque nous ne connaissons pas la valeur et l'état final de l'itération. La différence entre les deux est que la promesse que nous obtenons sera finalement décomposée en objets { value: any, done: boolean } ordinaires, et les itérateurs asynchrones peuvent être traités via des boucles for-await-of. Tout comme les boucles for-of sont utilisées pour synchroniser les itérateurs. [Recommandation associée : "tutoriel nodejs"]

const asyncIterable = [1, 2, 3];
asyncIterable[Symbol.asyncIterator] = async function*() {
  for (let i = 0; i < asyncIterable.length; i++) {
    yield { value: asyncIterable[i], done: false }
  }
  yield { done: true };
};

(async function() {
  for await (const part of asyncIterable) {
    console.log(part);
  }
})();

Contrairement à la boucle for-of habituelle, la boucle `for-await-of attendra que chaque promesse qu'elle reçoit soit résolue avant de continuer à s'exécuter. Suivant.

Outre les flux, aucune structure ne prend en charge l'itération asynchrone, mais le symbole asyncIterator peut être ajouté manuellement à n'importe quelle structure itérable.

Utiliser des itérateurs asynchrones sur des flux

Les itérateurs asynchrones sont très utiles lorsque vous travaillez avec des flux. Les flux lisibles, inscriptibles, duplex et transformés sont marqués du symbole asyncIterator.

async function printFileToConsole(path) {
  try {
    const readStream = fs.createReadStream(path, { encoding: &#39;utf-8&#39; });

    for await (const chunk of readStream) {
      console.log(chunk);
    }

    console.log(&#39;EOF&#39;);
  } catch(error) {
    console.log(error);
  }
}

Si vous écrivez le code de cette façon, vous n'avez pas besoin d'écouter les événements end et data lorsque vous parcourez chaque morceau de données, et la boucle for-await-of se terminera comme le flux se termine Terminer.

API pour les fonctionnalités paginées

Vous pouvez également facilement récupérer des données à partir de sources en utilisant la pagination via une itération asynchrone. Afin d'obtenir cette fonctionnalité, vous avez également besoin d'un moyen de reconstruire le corps de la réponse à partir du flux fourni par la méthode de requête Node https. Les itérateurs asynchrones peuvent également être utilisés ici, car les requêtes et les réponses https sont toutes deux des flux dans Node :

const https = require(&#39;https&#39;);

function homebrewFetch(url) {
  return new Promise(async (resolve, reject) => {
    const req = https.get(url, async function(res) {
      if (res.statusCode >= 400) {
        return reject(new Error(`HTTP Status: ${res.statusCode}`));
      }

      try {
        let body = '';

        /*
          代替 res.on 侦听流中的数据,
          可以使用 for-await-of,
          并把数据块附加到到响应体的剩余部分
        */
        for await (const chunk of res) {
          body += chunk;
        }
    
        // 处理响应没有响应体的情况
        if (!body) resolve({});
        // 需要解析正文来获取 json,因为它是一个字符串
        const result = JSON.parse(body);
        resolve(result);
      } catch(error) {
        reject(error)
      }
    });

    await req;
    req.end();
  });
}

Le code obtient des chats en faisant une requête à l'API Cat (https://thecatapi.com/) . Un délai de 7 secondes a également été ajouté pour empêcher un accès excessif et fréquent à l'API cat, car cela serait extrêmement contraire à l'éthique.

function fetchCatPics({ limit, page, done }) {
  return homebrewFetch(`https://api.thecatapi.com/v1/images/search?limit=${limit}&page=${page}&order=DESC`)
    .then(body => ({ value: body, done }));
}

function catPics({ limit }) {
  return {
    [Symbol.asyncIterator]: async function*() {
      let currentPage = 0;
      // 5 页后停止
      while(currentPage < 5) {
        try {
          const cats = await fetchCatPics({ currentPage, limit, done: false });
          console.log(`Fetched ${limit} cats`);
          yield cats;
          currentPage ++;
        } catch(error) {
          console.log(&#39;There has been an error fetching all the cats!&#39;);
          console.log(error);
        }
      }
    }
  };
}

(async function() {
  try {
    for await (let catPicPage of catPics({ limit: 10 })) {
      console.log(catPicPage);
      // 每次请求之间等待 7 秒
      await new Promise(resolve => setTimeout(resolve, 7000));
    }
  } catch(error) {
    console.log(error);
  }
})()

De cette façon, nous récupérerons automatiquement une page complète de photos de chats toutes les 7 secondes.

Une façon plus courante de naviguer entre les pages consiste à implémenter les méthodes next et previous et à les exposer en tant que contrôles :

function actualCatPics({ limit }) {
  return {
    [Symbol.asyncIterator]: () => {
      let page = 0;
      return {
        next: function() {
          page++;
          return fetchCatPics({ page, limit, done: false });
        },
        previous: function() {
          if (page > 0) {
            page--;
            return fetchCatPics({ page, limit, done: false });
          }
          return fetchCatPics({ page: 0, limit, done: true });
        }
      }
    }
  };
}

try {
    const someCatPics = actualCatPics({ limit: 5 });
    const { next, previous } = someCatPics[Symbol.asyncIterator]();
    next().then(console.log);
    next().then(console.log);
    previous().then(console.log);
} catch(error) {
  console.log(error);
}

Comme vous pouvez le voir, lorsque vous souhaitez obtenir le page de données Les itérateurs asynchrones peuvent être très utiles pour effectuer des choses comme le défilement infini sur l'interface utilisateur de votre programme.

Ces fonctionnalités sont disponibles dans Chrome 63+, Firefox 57+, Safari 11.1+.

Pouvez-vous penser à d’autres utilisations des itérateurs asynchrones ? Bienvenue à laisser un message ci-dessous !

Pour plus de connaissances sur la programmation, veuillez visiter : Vidéo de programmation ! !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer