node js,函数不等待响应

kxkpmulp  于 2021-06-10  发布在  Redis
关注(0)|答案(2)|浏览(375)

我对node js不熟悉。从逻辑上讲,await应该等待函数完成,然后运行下一行代码,但在我的函数中,即使使用await,它也不会等待进程(2)完成。我错过了什么?

const getDefaultTemplates = async (token) => {
  const emailertoken = process.env.EMAILER_AUTH_TOKEN;
  const key = 'defaultTemplates';
  // This should run first
  console.log('hi');
  let defaultTemplatesVar = '';
  let fromCache = 0;

  // This should run second. Need response from redisClient to return parent function
  const defaultTemplates = await redisClient.get(key, (err, data) => {
    if (err) {
      console.log(err);
    }
    // If data is found in cache
    if (data != null) {
      console.log('from cache');
      defaultTemplatesVar = JSON.parse(data);
      fromCache = 1;
      console.log('defaultTemplatesVar1 = ', defaultTemplatesVar);
    }
    return defaultTemplatesVar;
  });

  console.log('defaultTemplatesVar2 = ', defaultTemplatesVar);
  console.log('fromCache = ', fromCache);
  if (fromCache === 0) {
    // If data is not found in cache, call api
    // console.log('from api');
    try {
      const response = await axios.get(`${process.env.EMAILER_API_URL}/get-system-templates`, {
        headers: {
          Authorization: `bearer ${emailertoken}`,
        },
      });
      console.log('from data');
      redisClient.setex(key, 3600, JSON.stringify(response.data._embedded.get_system_templates));
      defaultTemplatesVar = response.data._embedded.get_system_templates;
      console.log('defaultTemplatesVar3 = ', defaultTemplatesVar);
    } catch (error) {
      console.error(error);
    }
  }

  // This should run at last, to return value to parent function getDefaultTemplates()
  console.log('bye');
  console.log('defaultTemplatesVar4 = ', defaultTemplatesVar);
  return defaultTemplates;
};

输出->

hi
defaultTemplatesVar2 =  
fromCache =  0
from cache
defaultTemplatesVar1 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]
from data
defaultTemplatesVar3 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]
bye
defaultTemplatesVar4 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]

输出应为1、2、3、4的系列。

t0ybt7op

t0ybt7op1#

回调函数不能为空 await ,要将回调fn转换为承诺fn,请 checkout https://www.npmjs.com/package/redis#promises .
如果您使用的是其他软件包,那么实际上可以通过

const redisGet = (key) => new Promise((resolve, reject) => {
  redisClient.get(key, (err, data) => {
    if (err) return reject(err);
    return resolve(data);
  });
});

// So you can do
const data = await redisGet(key);
// or
redisGet(key).then((data) => { ... }).catch((err) => { ... });

那你该怎么办

try {
  ...

  const data = await redisClient.get(key);

  if (data != null) {
    console.log('from cache');
    defaultTemplatesVar = JSON.parse(data);
    fromCache = 1;
    console.log('defaultTemplatesVar1 = ', defaultTemplatesVar);
  }
  const defaultTemplates = defaultTemplatesVar;
  ...
} catch (err) {
  console.error(err);
}

关于回调与承诺的简单教程

egmofgnx

egmofgnx2#

艾伦的回答解决了我的问题。
我唯一改变艾伦建议的是
const data=等待重新获取(key);
而不是
const data=等待redisclient.get(key);
因为后者返回的是“true”而不是实际值。

const redisGet = (key) => new Promise((resolve, reject) => {
  redisClient.get(key, (err, data) => {
    if (err) return reject(err);
    return resolve(data);
  });
});

// Api,Auth Done
const getDefaultTemplates = async (token) => {
  const emailertoken = process.env.EMAILER_AUTH_TOKEN;
  const key = 'defaultTemplates';
  // This should run first
  console.log('hi');
  let defaultTemplatesVar = '';
  let fromCache = 0;

  // This should run second. Need response from redisClient to return parent function
  try {
    const data = await redisGet(key);

    if (data != null) {
      console.log('from cache');
      defaultTemplatesVar = JSON.parse(data);
      fromCache = 1;
      console.log('defaultTemplatesVar1 = ', defaultTemplatesVar);
    }
    const defaultTemplates = defaultTemplatesVar;
  } catch (err) {
    console.error(err);
  }

  console.log('defaultTemplatesVar2 = ', defaultTemplatesVar);
  console.log('fromCache = ', fromCache);
  if (fromCache === 0) {
    // If data is not found in cache, call api
    // console.log('from api');
    try {
      const response = await axios.get(`${process.env.EMAILER_API_URL}/get-system-templates`, {
        headers: {
          Authorization: `bearer ${emailertoken}`,
        },
      });
      console.log('from data');
      redisClient.setex(key, 3600, JSON.stringify(response.data._embedded.get_system_templates));
      defaultTemplatesVar = response.data._embedded.get_system_templates;
      console.log('defaultTemplatesVar3 = ', defaultTemplatesVar);
    } catch (error) {
      console.error(error);
    }
  }

  // This should run at last, to return value to parent function getDefaultTemplates()
  console.log('bye');
  console.log('defaultTemplatesVar4 = ', defaultTemplatesVar);
  return defaultTemplatesVar;
};

输出1(当数据来自api时)

hi
defaultTemplatesVar2 = 
fromCache =  0
from data
defaultTemplatesVar3 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]
bye
defaultTemplatesVar4 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]

输出2(数据来自缓存时)

hi
from cache
defaultTemplatesVar1 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]
defaultTemplatesVar2 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]
fromCache =  1
bye
defaultTemplatesVar4 =  [ { name: 'versafix-1', description: 'The versatile template' },
  { name: 'givecentral', description: 'The Givecentral Template' } ]

相关问题