函数真的需要返回 promise 才能使 async-await 工作吗?

Posted

技术标签:

【中文标题】函数真的需要返回 promise 才能使 async-await 工作吗?【英文标题】:Does a function really need to return promise for async-await to work? 【发布时间】:2021-09-04 09:38:55 【问题描述】:

我的疑问是,我可以编写一个普通函数并等待调用该函数吗? 我会用一个例子更清楚地解释它 考虑这个函数

let splitStringAndConvertToInt=(data)=>
  let splitData=data.split("-")
  let bothValues=
    first:parseInt(splitData[0]),
    last:parseInt(splitData[1])
  
  return bothValues
 

上面是我要调用的函数, 下面是主要功能

let allocateRoomAccordingToNeeds=async (request)=>
  let mode=request.mode
  let totRooms=request.totalRooms
  let firstYearBtech=await splitStringAndConvertToInt(request.firstYearBtech)
  let secondYearBtech=await splitStringAndConvertToInt(request.secondYearBtech)
  let thirdYearBtech=await splitStringAndConvertToInt(request.thirdYearBtech)
  let fourthYearBtech=await splitStringAndConvertToInt(request.fourthYearBtech)
  let firstYearMtech=await splitStringAndConvertToInt(request.firstYearMtech)
  let secondYearMtech=await splitStringAndConvertToInt(request.secondYearMtech)
  let others=await splitStringAndConvertToInt(request.others)
  let tutors=await splitStringAndConvertToInt(request.tutors)
  let staff=await splitStringAndConvertToInt(request.staff)
  if (mode="Category" )
  
   Room.updateMany(Room_number: $gte:firstYearBtech.first,$lte:firstYearBtech.last , "$set":"position": "1 year btech", (err, writeResult) => if(err)console.log("error in 1 btech"+err) else
     Room.updateMany(Room_number: $gte:secondYearBtech.first,$lte:secondYearBtech.last , "$set":"position": "2 year btech", (err2, writeResult2) => if(err2)console.log("error in 2 btech"+err2) else
       Room.updateMany(Room_number: $gte:thirdYearBtech.first,$lte:thirdYearBtech.last , "$set":"position": "3 year btech", (err3, writeResult3) => if(err3)console.log("error in 3 btech"+err3) else
         Room.updateMany(Room_number: $gte:fourthYearBtech.first,$lte:fourthYearBtech.last , "$set":"position": "4 year btech", (err4, writeResult4) => if(err4)console.log("error in 4 b tech"+err4) else
           Room.updateMany(Room_number: $gte:firstYearMtech.first,$lte:firstYearMtech.last , "$set":"position": "1 year mtech", (err1m, writeResult1m) => if(err1m)console.log("error in 1 mtech"+err1m) else
             Room.updateMany(Room_number: $gte:secondYearMtech.first,$lte:secondYearMtech.last , "$set":"position": "2 year mtech", (err2m, writeResult2m) => if(err2m)console.log("error in 2 mtech"+err2m) else
               Room.updateMany(Room_number: $gte:others.first,$lte:others.last , "$set":"position": "others", (errO, writeResultO) =>if(errO)console.log("error in others"+errO) else
                 Room.updateMany(Room_number: $gte:tutors.first,$lte:tutors.last , "$set":"position": "tutors", (errT, writeResultT) => if(errT)console.log("error in tutor"+errT) else
                   Room.updateMany(Room_number: $gte:staff.first,$lte:staff.last , "$set":"position": "staff", (errS, writeResultS) => 
                      if(errS)
                         console.log("error in staff"+errS)
                      
                      else
                        console.log("Success allocation of Room")
                        res.send("Succes allocation of room")
                   )
                 )
               )
             )
           )
         )
       )
     )
   );
  
  else if(mode="Custom" )
   Room.updateMany("$set":"position": "Custom", (error, resultUp) => 
     if(error)
       console.log("error in Custom mode"+error)
     else
       console.log("successful upload of custom mode")
     )
  

以下是所有这些的根代码

   router.post('/authentication/changeallocationmode', function(req, res, next)
     //add code to assign same years to the given list if they are somewhere else and also add code to warn that given limit is not enough
       let vacate=req.body.vacate
       if(vacate==true)
         Room.updateMany($set:Roommates:["Null","Null","Null"],Occupied:false,Allocated:false)
         .then(()=>allocateRoomAccordingToNeeds(req.body))
       
       else allocateRoomAccordingToNeeds(req.body) /*this if-else is done to make it synchronous 
       so checking of vacate will be done and only after that other process will be done*/
     );

正如你在调用 splitToStringAndConvertToInt() 后看到的 有一个 Room.updateMany() 查询,因此需要在查询之前调用 await 以进行正确同步,因为 node.js 是异步的。 所以我需要知道的是,我可以这样调用 await 而不返回承诺吗?

【问题讨论】:

是的,你可以在非承诺上使用await,但如果你完全意识到这不是承诺,那么它是毫无意义的这样做可能会浪费 CPU 周期。 我想做的是延迟下一条要执行的指令,直到当前函数返回值,上面的代码也会这样做 是的,但不需要await - 每个splitStringAndConvertToInt 将在下一个开始之前完全运行,即使没有await @AshwinJoshy 如果您正在调用同步函数,那么它将阻塞线程,直到它完成执行并返回。你不需要做任何特别的事情来等待它,你也不需要async @AshwinJoshy 你“听说”错了 - 异步代码异步运行,而不是所有代码......像let a=1; let b=2 不会异步运行 【参考方案1】:

是的,函数应该返回promise,或者函数本身使用async-await,那么你可以使用await,否则await就没有意义了

但你的函数不需要是 promise 或 async-await 因为它不需要时间来完成

【讨论】:

实际上我的代码中还有另一个函数需要花费很多时间,您能否建议对函数 splitStringAndConvertToInt() 进行编辑,以便我可以在最后返回一个承诺。我是菜鸟承诺, @AshwinJoshy - 您代码中的其他函数与您提供的代码块无关 @JaromandaX 其实这不是完整的代码,我会总结完整的代码 @AshwinJoshy - 如果其余代码在您提供的代码之后,那也没关系

以上是关于函数真的需要返回 promise 才能使 async-await 工作吗?的主要内容,如果未能解决你的问题,请参考以下文章

在返回函数的变量之前,如何等待 promise 完成?

函数返回未定义,预期Promise或值和通知长时间延迟

异步支持返回不可链接的 Promise<void> 的函数

让 promise 在返回前等待几秒钟

当异步函数不应该返回 Promise 时,为啥我需要等待它?

为啥 Promise 构造函数需要一个在完成时调用 'resolve' 的函数,但 'then' 不需要 - 它返回一个值?