简体   繁体   English

nodejs 在全局范围内启用异步函数返回值

[英]nodejs enable async function return value in global scope

I need to use a value returned by an asynchronous function into a get request.我需要将异步函数返回的值用于 get 请求。 This is my code:这是我的代码:

let pwd;

async function getSecret() {

    const [version] = await smClient.accessSecretVersion({
        name: pgpwd
    });
    const pwd = version.payload.data.toString();
    console.log(`in  ${pwd}`);
    return pwd;
}


  promise1 =  getSecret().then((pwd) => console.log(`promise then ${pwd}`)   );
  
  console.log(promise1.then((pwd) => console.log(`promise1 ${pwd}`)));
  
  console.log(`global scope pwd ${pwd}`);

app.get('/pwd', (req, res) => {
    console.log(`get ${pwd}`);
    res.send(`pwd = ${pwd}!`);
});

I receive the value in promise.then but it is undefined in the global scope.我收到了 promise.then 中的值,但它在全局范围内未定义。

2020-09-20 11:27:00.909  > node index.js
2020-09-20 11:27:00.909  
2020-09-20 11:27:02.152  GET200363 B2 sPostmanRuntime/7.26.5 https://nodejs1-
2020-09-20 11:27:03.379 get undefined
2020-09-20 11:27:03.445 in 123456
2020-09-20 11:27:03.445 promise then 123456
2020-09-20 11:27:03.445 promise1 undefined
2020-09-20 11:27:04.634 get undefined

You don't need a global variable at all.您根本不需要全局变量。 Make your GET request callback async as well and await the result of your getSecret function in the callback.使您的 GET 请求回调也async ,并await回调中await getSecret函数的结果。

If getSecret is an expensive function to execute then you could wrap a function around it with a closure where the pwd value is stored in. Then when the function is called it checks if getSecret has been called before and calls it.如果getSecret是一个执行getSecret的函数,那么你可以用一个闭包来包裹它,其中存储pwd值。然后当函数被调用时,它会检查getSecret之前是否被调用过并调用它。 Or when it has been called before just return the result instead of calling getSecret again.或者当它之前被调用时只返回结果而不是再次调用getSecret

async function getSecret() {
  const [ version ] = await smClient.accessSecretVersion({
    name: pgpwd
  });
  const pwd = version.payload.data.toString();
  return pwd;
}

function storePwd() {
  let pwd = null;
  return async function() {
    if (pwd === null) {
      pwd = await getSecret();
    }
    return pwd;
  };
}

const getPwd = storePwd();

app.get('/pwd', async (req, res) => {
  const pwd = await getPwd();
  res.send(`pwd = ${pwd}!`);
});

There is no magic to this.这没有什么神奇之处。 You just need to assign it:你只需要分配它:

let pwd; // global

// ...

getSecret().then((localPwd) => { // renamed to something different so that we
                                 // don't shadow (hide) the global pwd 
    console.log(`promise then ${localPwd}`);
    pwd = localPwd; // assign to global variable
})

That's it.就是这样。 It's just a variable assignment.这只是一个变量赋值。 Nothing more complicated than that.没有比这更复杂的了。

Of course, doing it this way means that in the first few milliseconds when your app starts up before getSecret() returns the value of the global pwd is still undefined.当然,这样做意味着在getSecret()返回之前应用程序启动的最初几毫秒内,全局pwd值仍然是未定义的。 And if you happen to do a get request at this time you will get undefined.如果您此时碰巧执行了 get 请求,您将获得未定义的信息。 But after that it will have the value you expect.但在那之后,它将具有您期望的价值。 As long as you are OK with this limitation I don't see anything wrong with what you are doing.只要您接受此限制,我就看不出您在做什么有任何问题。

However, if you don't want your process to answer that get request then you must not define the get request until getSecret() returns.但是,如果您不希望您的进程响应该获取请求,那么在getSecret()返回之前,您不得定义获取请求。 Normally I would personally write code like this:通常我会亲自编写这样的代码:

getSecret().then((pwd) => {

    console.log(`promise then ${pwd}`);

    // ALL other app logic such as `get` definitions
    // are done inside the promise then:

    app.get('/pwd', (req, res) => {
        console.log(`get ${pwd}`);
        res.send(`pwd = ${pwd}!`);
    });
});

If you don't want the then function to be too long you can instead encapsulate your application logic in another function.如果您不希望then函数太长,您可以将应用程序逻辑封装在另一个函数中。 This is nothing new, C/C++ has something like this with the main() function:这不是什么新鲜事,C/C++ 有这样的main()函数:

let pwd;

function init () {
    app.get('/pwd', (req, res) => {
        console.log(`get ${pwd}`);
        res.send(`pwd = ${pwd}!`);
    });
}

getSecret().then((localPwd) => {

    console.log(`promise then ${localPwd}`);

    pwd = localPwd;

    init(); // start the app
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM