- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我想使用 gitter api 从一个房间获取所有消息。
我需要做的是发送 get api 请求,例如50 个项目,onComplete 我需要发送另一个包含 50 个项目的请求并跳过我已经收到的 50 个项目。执行此请求,直到他们不退还任何元素。所以:
我正在为此尝试 Promises,但我对它们有点困惑,不知道我是否做对了一切。主要问题是下一个Api调用和回调,如果所有调用都完成了。这是我的代码:
class Bot {
//...
_mysqlAddAllMessages(limit, skip) {
promise('https://api.gitter.im/v1/rooms/' + this.room + '/chatMessages' +
'?access_token=' + config.token + '&limit=' + limit + '&skip=' + skip)
.then(function (response) {
return new Promise(function (resolve, reject) {
response = JSON.parse(response);
if (response.length) {
console.log(`Starting - limit:${limit}, skip:${skip}`);
resolve(response);
}
})
}).then(response => {
let messages = response,
query = 'INSERT INTO messages_new (user_id, username, message, sent_at) VALUES ';
for (let message of messages) {
let userId = message.fromUser.id,
username = message.fromUser.username,
text = message.text.replace(/["\\]/g, '|'),
date = message.sent;
query += '("' + userId + '", "' + username + '", "' + text + '", "' + date + '"), ';
}
query = query.substr(0, query.length - 2);
return new Promise((resolve, reject) => {
this.mysql.getConnection((error, connection) => {
connection.query(query, (err) => {
if (err) {
reject(`Mysql Error: ${err}`);
} else {
connection.release();
resolve(console.log(`Added ${messages.length} items.`));
}
});
});
});
})
.then(()=> {
// what to do here
return this._mysqlAddAllMessagesf(limit, skip += limit)
})
.catch(function (er) {
console.log(er);
})
.finally(function () {
console.log('Message fetching completed.');
});
}
}
let bot = new Bot();
bot._mysqlAddAllMessages(100, 0);
也许你可以检查并帮助我?或者为此类事情提供类似的代码?
这是我将代码重构为:jsfiddle
最佳答案
你的代码让我很困惑。将 promises 与异步操作一起使用的最简单方法是“promisify”您现有的异步操作,然后使用 promises 编写所有逻辑。 “ promise ”某物意味着生成或编写一个返回 promise 的包装函数,而不是仅使用回调。
首先,让我们看一下整体逻辑。根据你的问题,你说你有一个 API,你想调用它来一次获取 50 个项目,直到你全部获取它们。这可以通过类似递归的结构来完成。创建一个内部函数来执行检索并返回一个 promise ,每次完成时再次调用它。假设您在此处涉及两个核心函数,一个称为 getItems()
,它从您的 API 获取项目并返回一个 promise ,另一个称为 storeItems()
,它将这些项目存储在您的数据库。
function getAllItems(room, chunkSize, token) {
var cntr = 0;
function getMore() {
return getItems(room, cntr, chunkSize, token).then(function(results) {
cntr += results.length;
if (results.length === chunkSize) {
return storeItems(results).then(getMore);
} else {
return storeItems(results);
}
});
}
return getMore();
}
此代码使用了链接 promise ,这是一个稍微高级但非常有用的 promise 功能。当您从 .then()
处理程序返回一个 promise 时,它会链接到先前的 promise 上,自动将它们全部链接在一起成为一系列操作。然后将最终的返回结果或错误通过原始 promise 返回给原始调用者。同样,此链中可能发生的任何错误都会一直传播回原始调用者。这在具有多个异步操作的复杂函数中非常有用,在这些函数中,如果使用常规回调,您不能简单地返回或抛出。
然后会这样调用:
getAllItems(this.room, 50, config.token).then(function() {
// finished successfully here
}, function(err) {
// had an error here
});
现在,我将处理一些示例,以创建低级别调用的 promise 版本以实现 getItems()
和 storeItems()
。稍后再回到这些。
我不太完全理解您的异步操作中的所有细节,因此这不是一个完整的示例,但应该说明整体概念,然后您可以提出任何必要的有关实现的澄清问题。
当 promise 一个函数时,您要做的主要事情是将处理回调和错误条件的脏工作封装到一个返回 promise 的核心函数中。然后,您可以在干净流畅的基于 promise 的代码中使用此函数,并允许您在控制流中使用 promise 的真正强大的错误处理功能。
为了请求这些项目,您似乎构建了一个 URL,该 URL 在 URL 中接受了一堆参数,然后您以 JSON 格式返回了结果。我假设这是一个 node.js 环境。因此,下面是如何使用 node.js request()
模块执行 getItems()
实现。这将返回一个 promise ,其解析值将是表示 api 调用结果的已解析 Javascript 对象。
function getItems(room, start, qty, token) {
return new Promise(function(resolve, reject) {
var url = 'https://api.gitter.im/v1/rooms/' + room + '/chatMessages' + '?access_token=' + token + '&limit=' + qty + '&skip=' + start;
request({url: url, json: true}, function(err, msg, result) {
if (err) return reject(err);
resolve(result);
});
});
}
对于存储项目,我们想要完成同样的事情。我们想创建一个函数,将数据作为参数存储并返回一个 promise ,它会在函数内部完成所有脏工作。所以从逻辑上讲,你想要这样的结构:
function storeItems(data) {
return new Promise(function(resolve, reject) {
// do the actual database operations here
// call resolve() or reject(err) when done
});
}
抱歉,我不太了解您对 mySql 数据库所做的工作,不足以完全填写此功能。希望这个结构能让您对如何完成它有足够的了解,或者在您遇到困难时提出一些问题。
注意:如果您使用像 Bluebird 这样的 Promise 库来添加额外的 promise 功能,那么 promise 一个现有的操作是 Bluebird 内置的东西,所以 getItems()
就变成了这样:
var Promise = require('bluebird');
var request = Promise.promisifyAll(require('request'));
function getItems(room, start, qty, token) {
var url = 'https://api.gitter.im/v1/rooms/' + room + '/chatMessages' + '?access_token=' + token + '&limit=' + qty + '&skip=' + start;
return request.getAsync({url: url, json: true});
}
关于javascript - 在递归中使用 javascript promises 进行 Api 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32808862/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!