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

Node.js循环中Promise使用异常求助:Twitter推文翻译流程问题

问题分析与解决方案

我一眼就看出你遇到的问题啦——Promise.all()的执行时机完全错了!

问题根源

T.get()是Twitter提供的异步API调用,它的回调函数要等API返回数据后才会执行。但你把Promise.all(promises)写在了T.get()的外面,这就导致:在Twitter请求还没拿到数据、promises数组还是空数组的时候,Promise.all就已经运行了。空数组的Promise.all会立刻resolve,所以你会看到"ALL PROMISES DONE"直接打印出来,完全没等翻译任务开始。

解决方案1:调整Promise.all的位置

最简单的修复方式是把Promise.all移到T.get()的回调函数内部,确保只有在promises数组被填充完翻译任务后,才去等待所有Promise完成:

var Twit = require('twit')
var T = new Twit({
 consumer_key: '...',
 consumer_secret: '...',
 access_token: '...',
 access_token_secret: '...',
 timeout_ms: 60*1000, // optional HTTP request timeout to apply to all requests.
})

//TWITTER
app.post('/twitter/search/hashtags', function (req, res) {
 // TWITTER QUERY PARAMS
 var params = {
 q: req.body.search,
 count: 2,
 //lang: 'fr'
 }
 //GData
 var bloc = [];
 var promises = [];

 // TWITTER API GET INFORMATION
 T.get('search/tweets', params, function(err, data, response) {
 // if there no errors
 if (!err) {
 //PROCESSING DATA FROM TWITTER
 if(data){
 for(var i= 0; i < data.statuses.length; i++){
 //translate all text string which are not in french
 var lang = data.statuses[i].lang;
 var str = data.statuses[i].text;
 if(lang != "fr"){
 promises.push(translate_str(data.statuses[i].user.screen_name, str, lang));
 }
 }
 }

 // 把Promise.all移到这里!确保promises数组已经填充完毕
 Promise.all(promises)
 .then(function(translatedData){
 console.log("ALL PROMISES DONE");
 console.log(translatedData);
 // 在这里把结果返回给前端
 res.send(translatedData);
 })
 .catch(function(err){ 
 console.error(err);
 res.status(500).send('Translation failed');
 });
 }
 // if unable to Search a tweet
 else {
 console.log('Something went wrong while SEARCHING...');
 console.log(err);
 res.status(500).send('Twitter search failed');
 }
 });

 //TRANSLATE - 优化:去掉不必要的Promise嵌套
 function translate_str(name, str, lang){
 return translate(str, {from: lang, to: 'fr'})
 .then(res => {
 console.log('TRANSLATED INTO :');
 console.log(res.text);
 //SENTIMENT ANALYSIS
 var r1 = sentiment(res.text, 'fr');
 console.log(r1.score);
 console.log(r1.positive);
 //IF SCORE POSITIVE THEN PUSH TO FRONT
 if(r1.score > 0){
 return { name: name, text: res.text, lang: lang, selected: false };
 }
 // 分数非正的情况可以返回null,后续可以过滤掉
 return null;
 })
 .catch(err => {
 console.error(err);
 throw err; // 抛出错误让Promise.all捕获
 });
 }
})

解决方案2:用Promise包装+async/await让代码更整洁

如果想避免回调嵌套,让代码逻辑更清晰,可以把T.get()包装成Promise,然后用async/await来编写异步逻辑:

var Twit = require('twit')
var T = new Twit({
 consumer_key: '...',
 consumer_secret: '...',
 access_token: '...',
 access_token_secret: '...',
 timeout_ms: 60*1000, // optional HTTP request timeout to apply to all requests.
})

// 把T.get包装成Promise函数
function fetchTwitterTweets(params) {
 return new Promise((resolve, reject) => {
 T.get('search/tweets', params, (err, data) => {
 if (err) reject(err);
 else resolve(data);
 });
 });
}

//TWITTER
app.post('/twitter/search/hashtags', async function (req, res) {
 try {
 // TWITTER QUERY PARAMS
 const params = {
 q: req.body.search,
 count: 2,
 //lang: 'fr'
 };

 // 等待Twitter API返回数据
 const data = await fetchTwitterTweets(params);

 const promises = [];
 if(data){
 for(let i= 0; i < data.statuses.length; i++){
 const lang = data.statuses[i].lang;
 const str = data.statuses[i].text;
 if(lang != "fr"){
 promises.push(translate_str(data.statuses[i].user.screen_name, str, lang));
 }
 }
 }

 // 等待所有翻译任务完成
 const translatedData = await Promise.all(promises);
 console.log("ALL PROMISES DONE");
 console.log(translatedData);
 // 返回过滤掉非正分数的结果给前端
 res.send(translatedData.filter(item => item !== null));
 } catch(err) {
 console.error('Error occurred:', err);
 res.status(500).send('Operation failed');
 }
});

//TRANSLATE - 优化后的函数
function translate_str(name, str, lang){
 return translate(str, {from: lang, to: 'fr'})
 .then(res => {
 console.log('TRANSLATED INTO :');
 console.log(res.text);
 const r1 = sentiment(res.text, 'fr');
 console.log(r1.score);
 console.log(r1.positive);
 return r1.score > 0 ? { name, text: res.text, lang, selected: false } : null;
 })
 .catch(err => {
 console.error(err);
 throw err;
 });
}

额外优化点

  • 你的translate_str函数原本手动包了一层Promise,其实完全没必要——因为translate()已经返回Promise了,直接return它的链式调用即可,这样代码更简洁。
  • 可以在最后过滤掉translate_str返回的null值(也就是分数非正的推文),只把符合条件的数据返回给前端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:36:24