gpt4 book ai didi

javascript - 在递归中使用 javascript promises 进行 Api 调用

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:58:50 25 4
gpt4 key购买 nike

我想使用 gitter api 从一个房间获取所有消息。

我需要做的是发送 get api 请求,例如50 个项目,onComplete 我需要发送另一个包含 50 个项目的请求并跳过我已经收到的 50 个项目。执行此请求,直到他们不退还任何元素。所以:

  • 发送api请求
  • json解析
  • :请求有项目
    • 用这个项目做一个sql查询
    • 继续查询
    • 发送下一个 api 请求(递归?)
    • >?如果下一个 api 请求中没有更多项目 - 显示完成消息
  • : 请求没有项目
    • 中止消息

我正在为此尝试 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com