async/await未正常工作:JavaScript异步流程执行顺序异常求助
我是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

