Javascript 理解NodeJS上的异步/等待

Javascript 理解NodeJS上的异步/等待,javascript,node.js,asynchronous,async-await,Javascript,Node.js,Asynchronous,Async Await,我想我对它的理解可能会受到我使用.NET的异步/await的经验的影响,因此我想举一些代码示例: 我试图让express控制器在返回响应之前等待5秒: const getUsers = async (ms) => { var wait = ms => new Promise(resolve => setTimeout(resolve, ms)); await wait(ms); }; export const index = (req, res) => {

我想我对它的理解可能会受到我使用.NET
异步/await
的经验的影响,因此我想举一些代码示例:

我试图让express控制器在返回响应之前等待5秒:

const getUsers = async (ms) => {
  var wait = ms => new Promise(resolve => setTimeout(resolve, ms));

  await wait(ms);
};


export const index = (req, res) => {
  async () => {
    await getUsers(5000);

    res.json([
      {
        id: 1,
        name: 'John Doe',
      },
      { id: 2,
        name: 'Jane Doe',
      },
    ]);
  };
};
此代码不起作用,浏览器不断加载,从不显示任何内容

我构建的
getUser
函数和控制器方法都是基于我对其工作原理的(错误)理解,因此我希望得到一些澄清和更正:

1。我应该在什么时候使用
wait

据我所知,在调用
async
函数之前,应该使用
wait
。这是正确的吗?另外,为什么我可以在返回承诺的非异步函数之前调用wait

2。什么时候应该使用
async


据我所知,您将函数标记为
async
函数,以便可以使用
await
关键字调用它。这是正确的吗?另外,[为什么]我必须将我的
等待getUsers(5000)
调用封装在匿名异步函数中?

为了澄清一些疑问-

  • 您可以将
    wait
    与任何返回承诺的函数一起使用。您等待的函数不一定是
    async
  • 如果要在函数中使用
    wait
    关键字,则应使用
    async
    函数。如果您不打算在函数中使用
    wait
    关键字,则不需要使该函数
    async
  • async
    函数默认返回承诺。这就是您能够等待
    异步
    函数的原因 从-

    调用异步函数时,它返回一个承诺

    就你的代码而言,它可以这样写-

    const getUsers = (ms) => { // No need to make this async
        return new Promise(resolve => setTimeout(resolve, ms));
    };
    
    // this function is async as we need to use await inside it
    export const index = async (req, res) => {
        await getUsers(5000);
    
        res.json([
          {
            id: 1,
            name: 'John Doe',
          },
          { id: 2,
            name: 'Jane Doe',
          },
        ]);
    };
    

    异步等待只是承诺的语法糖

    当您希望代码在函数的完整部分上运行时,您可以像使用承诺一样使用它们

    async function asyncOperation(callback) {
        const response = await asyncStep1();
        return await asyncStep2(response);
    }
    
    let value = await myPromisifiedFunction(); 
    
    如果使用promises land语法,则是完全相同的:

    function asyncOperation() {
      return asyncStep1(...)
        .then(asyncStep2(...));
    }
    
    新的async/await语法允许您仍然使用Promissions,但它消除了向链式then()方法提供回调的需要

    回调直接从异步函数返回,就像它是一个同步阻塞函数一样

    async function asyncOperation(callback) {
        const response = await asyncStep1();
        return await asyncStep2(response);
    }
    
    let value = await myPromisifiedFunction(); 
    
    当您计划在函数中使用wait时,您应该使用async关键字标记函数(如在c#中)


    您不必将getUsers创建为匿名函数

    您可以在
    异步
    函数中等待任何承诺。
    wait
    之后的代码将在您等待的承诺完成后执行

    这是经典JavaScript回调的一个很好的替代方案

    我写了一篇关于它的博客->我希望这会对你有所帮助

    Javascript中的异步函数
    async
    关键字将常规JS函数声明转换为异步函数声明:

    function syncFunc {// dostuff}
    async function asyncFunc {// dostuff} // the async keyword is placed before the function keyword
    
    异步函数返回一个承诺:

    • 当异步函数返回一个值时,将使用返回的值解析承诺
    • 当异步函数抛出异常或某个值时,承诺将被抛出的值拒绝
    在异步函数中,可以使用
    wait
    关键字<代码>等待放在承诺之前会导致异步函数暂停,直到承诺得到解决(拒绝或履行)

    • 。当承诺已满时,
      wait
      表达式的值为已满承诺的值
    • 当承诺被拒绝时,
      wait
      表达式抛出被拒绝的值
    例子:
    函数makePromise(x){
    返回新承诺(解决=>{
    设置超时(()=>{
    决议(x);
    }, 1000);
    });
    }
    异步函数asyncFunc(){
    var x=await makePromise(1);//函数在此暂停,直到承诺实现为止
    console.log(x);//日志1
    返回x;
    }
    const returnedProm=asyncFunc();//异步func返回一个承诺
    returnedProm.then((x)=>console.log(x));
    
    //这个承诺是通过async func的返回值来实现的,因此这个日志1
    不将内容包装在异步匿名函数中,而在代码中,这个函数也永远不会执行。相反,要使索引函数异步,并删除函数wrap和return res.json。这个解释非常清楚。现在,剩下的就是将导出的异步函数
    index
    (这是一个返回承诺的函数)与express router连接起来,与一个接受承诺的
    router.get
    变体连接起来。这是正确的吗?是的,在Express中你可以像这样使用它-
    路由器。get('/users',index)
    。换句话说,异步函数可以通过wait关键字使异步编程像同步编程一样运行。因此,您的应用程序更容易理解。