Вложенный для l oop в nodejs, кажется, работает асинхронно - PullRequest
0 голосов
/ 16 февраля 2020

Итак, у меня есть два цикла for, и один вложен в другой, но результаты, которые они возвращают, по-видимому, запускают первый l oop и возвращают его результаты, чем вложенный l oop. Как я могу заставить его работать синхронно? Например, все topicData печатаются подряд вместо того, чтобы печатать один topicData и переходить к вложенному для l oop. Я не уверен, что это правильный способ реализовать asyn c await. Любые указатели будут оценены. Спасибо

exports.create = (event, context, callback) => {

  var topicTimestamp = "";
  var endpoint = "";

  sns.listTopics(async function(err, data) {
    if (err) {
      console.log(err, err.stack);
    } else {
      console.log(data);
      for (var topic in data.Topics){ //first loop
        //var topicData = "";
        //retrieve each topic and append to topicList if it is lakeview topic
        var topicData =  await data.Topics[topic].TopicArn;
        topicTimestamp = topicData.slice(22, 34); //get only the topic createdAt

        var params = {
          TopicArn: topicData //topicData
        };
        console.log("SUBS per" + params.TopicArn);

        //retrieve subscriptions attached to each topic
        sns.listSubscriptionsByTopic(params, async function(err, subscriptionData){
          console.log(subscriptionData);
          //console.log("SUBS per" + params.TopicArn);
          if (err) {
            console.log(err, err.stack); // an error occurred
          } else  {
            var endpointList = [];
            for (var sub in subscriptionData.Subscriptions) { //nested loop

              endpoint = await subscriptionData.Subscriptions[sub].Endpoint;

              console.log("ENDPOINT:: " + endpoint);
              endpointList.push(endpoint);
            }
          } // end of else listSub

          //put topic info into table
          var topicsParams = {
            TableName: tableName,
            Item: {
              id: uuidv4(),
              createdAt: timestamp,
              topicCreatedAt: topicTimestamp,
              topic: topicData,
              phoneNumbers: endpointList
            },
          };

          endpointList = [];  //reset to empty array

          dynamoDb.put(topicsParams, (error) => {...}

1 Ответ

0 голосов
/ 16 февраля 2020

Здесь есть несколько проблем

  • Вы пытаетесь сделать код стиля обратного вызова в циклах, пока у вас есть методы обещания.
  • Вы также можете делать вещи параллельно, используя promise.all
  • Из-за стиля обратного вызова код очень сложен
  • Вы ожидаете, когда это не требуется. Например, в обратном вызове

Вы можете попытаться использовать этот способ

exports.create = async (event, context, callback) => {

  try {
    let topicTimestamp = "";
    let endpoint = "";
    const data = await sns.listTopics().promise();
    // eslint-disable-next-line guard-for-in
    for (const topic in data.Topics) { // first loop
    // var topicData = "";
    // retrieve each topic and append to topicList if it is lakeview topic
      const topicData = data.Topics[topic].TopicArn;
      topicTimestamp = topicData.slice(22, 34); // get only the topic createdAt

      const params = {
        "TopicArn": topicData // topicData
      };
      console.log(`SUBS per${ params.TopicArn}`);

      const subscriptionData = await sns.listSubscriptionsByTopic(params).promise();
      const endpointList = [];
      // eslint-disable-next-line guard-for-in
      for (const sub in subscriptionData.Subscriptions) { // nested loop
        endpoint = subscriptionData.Subscriptions[sub].Endpoint;
        console.log(`ENDPOINT:: ${ endpoint}`);
        endpointList.push(endpoint);
      }

      // put topic info into table
      const topicsParams = {
        "TableName": tableName,
        "Item": {
          "id": uuidv4(),
          "createdAt": timestamp,
          "topicCreatedAt": topicTimestamp,
          "topic": topicData,
          "phoneNumbers": endpointList
        }
      };

      // Similarly use dynamodb .promise functions here
    }
  } catch (Err) {
    console.log(Err);
  }
};

aws-sdk по умолчанию поддерживает стиль обратного вызова. Чтобы преобразовать их в обещание, вам нужно добавить .promise() в конце.

В данный момент этот пример использует для l oop, но вы можете сделать то же самое, используя Promise.all.

Надеюсь, это поможет.

...