在 then 回调中使用 await - 保留关键字“await”

Posted

技术标签:

【中文标题】在 then 回调中使用 await - 保留关键字“await”【英文标题】:Using await in then callback - the keyword 'await' is reserved 【发布时间】:2018-06-18 18:02:33 【问题描述】:

在 node.js 中,我有一个数据库事务,我想在 then 回调中调用 async 方法,但我收到错误消息 the keyword 'await' is reserved

这是异步saveImage函数:

const saveImage = async (parsedLink) => 
  AWS.config.region = config.awsSettings.region;
  AWS.config.accessKeyId = config.awsSettings.accessKeyId;
  AWS.config.secretAccessKey = config.awsSettings.secretAccessKey;
  const bucket = new AWS.S3(
    params: 
      Bucket: config.awsSettings.images_bucket_name,
    ,
  );

  const currentDateString = new Date().toISOString().replace(/\:|\./g, '-');
  const bodystream = new Buffer(parsedLink.imgUrl, 'binary');
  const imageUrlDomain = parseDomain(parsedLink.linkUrl).domain;

  const params = 
    Key: `$parsedLink.id/$imageUrlDomain_$currentDateString$parsedLink.imgType`,
    ContentType: parsedLink.imageMime,
    ContentEncoding: 'base64',
    Body: bodystream,
  ;

  const resultPromise = await bucket.upload(params).promise();
  return resultPromise.Location;
;

如果我想使用saveImage 函数,我会收到错误消息。

module.exports.addTestObject = async (ctx) => 
  const testObj = ctx.request.body;
  try 
    switch (testObj.type) 
      case interestT.getType.link: 
        const knexTestObject = TestObject.knex();
        transaction(knexTestObject, trx =>
            TestObject.query(trx)
              .insert(
                interestDate: testObj.date,
              )
              .then(newInterest => 
                // save image
                if (parsedLink.saveImg) 
                  parsedLink.imgUrl = await saveImage(testObj);
                

                newInterest.$relatedQuery('linkInterestsRel', trx).insert(
                  linkHeader: testObj.linkHeader,
                ),
              
              ),
          )
          .then((linkInterest) => 
            console.log(linkInterest);
          )
          .catch((err) => 
            throw err;
          );
        break;
      
      default:
        break;
    
    ctx.response.body = interestObj;
   catch (err) 
    const statusCode = err.status || 400;
    ctx.throw(statusCode, err.message);
  
;

【问题讨论】:

你只能在async函数中使用await,并且你的.then()回调不是async -> .then(async (newInterest) => @JonasW。谢谢,你能把它写成答案吗?然后我可以关闭这个问题。 呃,不要在 async 函数中使用 then 回调。 【参考方案1】:

常规的functions 同步运行直到它们返回。因此,您不能在其中使用await,因为您不能以同步方式等待异步事件。

javascript 也有 async functions,它们看起来像常规函数,但在概念上完全不同:它们同步运行直到达到 await,然后它们停止并在等待的 Promise 后继续解决。因此,它们不能同步返回结果,而是返回一个 Promise,然后在函数完成执行时解析。

因此您需要将您的函数转换为异步函数:

 async function getUsername()  // <-- async keyword here
    return (await getUser()).name; // <-- await can be used inside
 

现在这也可以在 .then 回调中工作:

 getUser().then(async function(user) 
    const friends = await getFriends(user);
    // ...
 )

但这在某种程度上将抽象异步函数与其底层的原始 Promise 混合在一起。如果你只是 await Promise 而不是添加 .then 回调,代码会变得更具可读性:

 (async function() 
    const user    = await getUser();
    const friends = await getFriends(user);
 )();

具体问题可以改写为:

 const linkInterest = await transaction(knexTestObject, async trx => 
     const newInterest = await TestObject.query(trx)
          .insert(  interestDate: testObj.date,   );

     if (parsedLink.saveImg) 
       parsedLink.imgUrl = await saveImage(testObj);
     

    await newInterest.$relatedQuery('linkInterestsRel', trx)
       .insert(  linkHeader: testObj.linkHeader, ),
);

【讨论】:

如果想使用await 进行查询,transaction 回调仍然需要是async function(确实应该)。

以上是关于在 then 回调中使用 await - 保留关键字“await”的主要内容,如果未能解决你的问题,请参考以下文章

async await 的用法

如何在写await async的时候不用try catch

async await

浅谈async/await

async和await 总结

解决异步问题,教你如何写出优雅的promise和async/await,告别callback回调地狱!