You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

async/await未正常工作:JavaScript异步流程执行顺序异常求助

问题:Async/Await 顺序执行异常,sendImageMessage 最后执行

我是JavaScript中async、await和promise特性的新手。我的实现代码如下:

async function sendTextMessage(text) { 
  console.log("----1----"); 
  var messageData = { message: { text: text } }; 
  await callSendAPI(messageData); 
} 

async function sendImageMessage(imageUrl) { 
  console.log("----2----"); 
  var messageData = { message: { url: imageUrl } }; 
  await callSendAPI(messageData); 
} 

async function sendQuickReply(replies) { 
  console.log("----3----"); 
  var messageData = { message: { text: text, quick_replies: replies } }; 
  await callSendAPI(messageData); 
} 

async function callSendAPI(messageData) { 
  await request({ 
    uri: 'https://graph.facebook.com/v2.6/me/messages', 
    qs: { access_token: config.FB_PAGE_TOKEN }, 
    method: 'POST', 
    json: messageData 
  }, function(error, response, body) { 
    if (!error && response.statusCode == 200) { 
      var recipientId = body.recipient_id; 
      var messageId = body.message_id; 
      if (messageId) { 
        console.log("Successfully sent message with id %s to recipient %s", messageId, recipientId); 
      } else { 
        console.log("Successfully called Send API for recipient %s", recipientId); 
      } 
    } else { 
      console.error("Failed calling Send API", response.statusCode, response.statusMessage, body.error); 
    } 
  }); 
}

我在send函数中按顺序调用这些函数:

async function send(){ 
  await sendTextMessage(text); 
  await sendImageMessage(img); 
  await sendQuickReply(replies) 
} 
send()

但实际响应显示sendImageMessage()最后执行,怀疑是传入imageUrl时该函数未准备好导致响应生成异常,请问该如何解决?


回答

嘿,这个问题的核心其实不在imageUrl的准备上,而是你的callSendAPI函数没有正确结合Promise使用——这才是导致顺序混乱的根本原因!

你现在用的是request库的回调版本,而await只能等待Promise对象,但当前callSendAPI里的await完全没起到作用:因为回调模式的request不会返回Promise,这个await相当于等待了一个立即resolve的空值,所以各个send函数会“假等待”,直接继续执行下一个,最终导致执行顺序完全乱掉。

解决步骤:包装request为Promise

把callSendAPI改成返回Promise的形式,这样await才能真正等待API请求完成:

async function callSendAPI(messageData) { 
  // 用Promise包裹request的回调逻辑
  return new Promise((resolve, reject) => {
    request({ 
      uri: 'https://graph.facebook.com/v2.6/me/messages', 
      qs: { access_token: config.FB_PAGE_TOKEN }, 
      method: 'POST', 
      json: messageData 
    }, function(error, response, body) { 
      if (!error && response.statusCode == 200) { 
        var recipientId = body.recipient_id; 
        var messageId = body.message_id; 
        if (messageId) { 
          console.log("Successfully sent message with id %s to recipient %s", messageId, recipientId); 
        } else { 
          console.log("Successfully called Send API for recipient %s", recipientId); 
        }
        resolve({ recipientId, messageId }); // 请求成功时标记Promise完成
      } else { 
        const errorInfo = { 
          statusCode: response?.statusCode, 
          statusMessage: response?.statusMessage, 
          error: body?.error 
        };
        console.error("Failed calling Send API", errorInfo);
        reject(errorInfo); // 请求失败时标记Promise异常
      } 
    });
  });
}

额外小修复

你的sendQuickReply函数里引用了未定义的text变量,这会导致运行报错,记得把它改成正确的参数传入:

async function sendQuickReply(text, replies) { 
  console.log("----3----"); 
  var messageData = { message: { text: text, quick_replies: replies } }; 
  await callSendAPI(messageData); 
}

修改完成后,await callSendAPI(messageData)就会真正等待API请求结束后,再执行下一个send函数,sendTextMessage→sendImageMessage→sendQuickReply就会严格按顺序执行了。

可选优化:使用Promise版request库

如果你的项目允许,也可以直接使用request-promise(Promise版的request),代码会更简洁:

// 先安装依赖:npm install request-promise
const rp = require('request-promise');

async function callSendAPI(messageData) { 
  try {
    const body = await rp({ 
      uri: 'https://graph.facebook.com/v2.6/me/messages', 
      qs: { access_token: config.FB_PAGE_TOKEN }, 
      method: 'POST', 
      json: messageData 
    });
    var recipientId = body.recipient_id; 
    var messageId = body.message_id; 
    if (messageId) { 
      console.log("Successfully sent message with id %s to recipient %s", messageId, recipientId); 
    } else { 
      console.log("Successfully called Send API for recipient %s", recipientId); 
    }
    return { recipientId, messageId };
  } catch (error) {
    console.error("Failed calling Send API", error.statusCode, error.statusMessage, error.error);
    throw error;
  }
}

内容的提问来源于stack exchange,提问作者Nikhil Savaliya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:41:30