Как вернуться из вложенной функции в Node.js? - PullRequest
0 голосов
/ 26 октября 2019

Я оборачиваю свою функцию DynamoDB в другую функцию, и у меня возникают проблемы с возвратом ее в const "item". Что мне здесь не хватает?

Работает:

    const params = {
      TableName: table,
      Key: {
        id: id
      },
    };

    dynamoDb.get(params, (error, result) => {
      if (error) {
        console.error(error);
        callback(null, {
          statusCode: error.statusCode || 501,
          body: 'Couldn\'t fetch the item.',
        });
        return;
      }

      const item = result.Item
    })

Не работает (возвращает неопределенное):

  const getFromDb = () => {
    const params = {
      TableName: table,
      Key: {
        id: id
      },
    };

    dynamoDb.get(params, (error, result) => {
      if (error) {
        console.error(error);
        callback(null, {
          statusCode: error.statusCode || 501,
          body: 'Couldn\'t fetch the item.',
        });
        return;
      }

      return result.Item
    })
  }

  // Get from db
  const item = getFromDb()
  // do stuff with result item...

1 Ответ

1 голос
/ 26 октября 2019

То, что в данный момент происходит в вашем коде, это getFromDb, функция будет запускаться dynamoDb.get(...) и сразу же возвращаться (неопределенно в вашем случае, потому что внутри getFromDb нет оператора return). К тому времени, когда getFromDb вернется, ваш запрос DynamoDb еще даже не будет решен, он будет решен в какой-то момент в будущем и вызовет обратный вызов, который вы предоставили (error, result) => { ... }

Чтобы выполнить то, что вы описали, вам нужноto:

  1. make getFromDb return Promise , который разрешится только после того, как ваш запрос разрешит
  2. await для этой функции при ее вызове, получив результат вчто ваше Обещание разрешает (или и ошибку, если оно отклоняет)

.

// marking this function async is not required but good to have
// to not forget that this function returns a promise, not immediate result
const getFromDb = async () => {
  // wrapped body in a promise
  return new Promise((resolve, reject) => {
    const params = {
      TableName: table,
      Key: {
        id: id
      },
    }

    dynamoDb.get(params, (error, result) => {
      if (error) {
        // in case of error, we reject promise with that error
        reject(error)
        return
      }
      // otherwise, we resolve with result
      resolve(result.Item)
    })
  })
}

// usage with async/await
// I wrapped significant code in asynchronous function f and then called it
// just to emphasize that you can only use async/await inside async function
// if you are already in async function, you don't need to do this
const f = async () => {
  try {
    const item = await getFromDb();
    console.log(item)
  } catch(error) {
    // the error we rejected with
    console.error(error)
  }
}

f()


// alternative way without async/await, using Promise chaining
getFromDb()
  .then(item => console.log(item))
  .catch(error => console.error(error))
...