gpt4 book ai didi

javascript - 使用 Airtable.js 时如何从 done() 回调返回数据?

转载 作者:行者123 更新时间:2023-11-30 20:33:19 24 4
gpt4 key购买 nike

首先,让我从我想要实现的目标开始。我想查询 Airtable 中的一个表,其中包含来自链接表的数据。 Airtable 返回链接表中记录的 ID,因此我需要对每条记录进行第二次查找以获取我想要的数据(例如 Name)。最后,我想向客户端返回链接记录中的 ID 其他字段。问题是,由于 API 的异步特性和我缺乏理解,我未能实现这一目标。

到目前为止,我能做的最好的事情就是在他们的 API 的 done() 回调中执行一些代码。问题是这不是可扩展的,因为这意味着我会让自己陷入回调 hell 。 (至少,到目前为止,我认为这是我能够确定的。)

这是我的代码(仅供引用,这是要在 Azure 函数中运行的代码):

var Airtable = require("airtable");
var airtableApiKey = process.env.airtableApiKey;

module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');

var base = new Airtable({
apiKey: airtableApiKey
}).base('appBASEID');
var resultObj;
var accumulator = [];

base('Products').select({
sort: [{
field: 'Identifier',
direction: 'asc'
}]
}).eachPage(function page(records, fetchNextPage) {
records.forEach(function (record) {
context.log('Retrieved ', record.get('Identifier'));
context.log('Retrieved ', record.get('Vendor'));

accumulator.push(record._rawJson);

// base('Vendors').find(record.get('Vendor')[0], function( err, record) {
// if (err) { context.error(err); return; }
// context.log(record.get('Name'));
// });
});
fetchNextPage();
}, function done(error) {

context.res = {
// status: 200, /* Defaults to 200 */
body: JSON.parse(JSON.stringify(accumulator))
};

context.done();
});
};

您可以看到我在 .eachPage() 部分中注释了一些行,因为正如我在处理此部分时了解到的那样,该代码未按我预期的顺序执行.

我如何foreach通过accumulator.find()我需要的记录?

最佳答案

看起来您遇到的问题是 done 回调在 forEach 中的 find 调用完成之前执行。 forEach 可能会阻塞,但每个 find 调用都不会。因此,您继续获取更多页面,并最终获取所有页面,您成功获取所有链接记录之前。

这是我为管理它而编写的代码。请注意,它很长,可能还有改进的余地。我还尝试处理您的链接字段可能包含多个元素以及您可能有多个您有兴趣查找的链接字段列的情况。

var base = Airtable.base(base_id)
var table = base.table(table_name);

// create a map between the linked record columns in your table
// and the table that those linked record's point to
var linked_fields = {
'Local Column A': 'Foreign Table X',
'Local Column B': 'Foreign Table Y'
}

// manage all records and promises
var all_records = [];
var all_promises = [];

// cycle through all pages in our table
table.select().eachPage(function page(records, fetchNextPage) {
// for each record, go through each linked field and pull all associated linked records
var page = records.map((record) => {
// for each column, we want to check if the given record has any linked records
// if it does, then go ahead and perform a fetch in the foreign table
// linked record fields are a list because there can be multiple linked records
// so we have to loop through each ID
var record_promises = Object.keys(linked_fields).map((field) => {
if (record.fields[field] !== undefined) {
let t = base.table(linked_fields[field]);
var linked_promises = record.fields[field].map((foreign_record_id) => {
return t.find(foreign_record_id);
});

// wait for this record to get all of its linked fields
return Promise.all(linked_promises).then((values) => {
// for each linked field, we don't need all the extra Airtable SDK noise
// so just use the rawJSON structure from the foreign record
// but update both the rawJson and fields structures in the local record
values = values.map((v) => {
return v._rawJson;
});
record.fields[field] = values;
record._rawJson.fields[field] = values;
});
}
});

// wait for the record to finish updating all linked fields
// and then return the record
return Promise.all(record_promises).then(() => {
return record;
});
});

// we have to wait for all records in this page to get updated information
// we can use all_promises to track all of our active promises
all_promises.push(Promise.all(page));

// we don't need to wait for everything to resolve before fetching the next page
// and we probably don't want to wait.
// Airtable pagination will die if you wait too long in between calls
// and you have to start all over
fetchNextPage();

}, function done(error) {
if (error) {
reject(error);
}

// once we've fetched all pages, wait for all those pages to settle
// we will get a list of lists at the end of this, where each page is a different list
// so we can now flatten it into a single list by pushing all records into all_records
Promise.all(all_promises).then((results) => {
for (var i in results) {
all_records.push.apply(all_records, results[i]);
}
context.res = {
// status: 200, /* Defaults to 200 */
body: JSON.parse(JSON.stringify(all_records))
};

context.done();
}).catch((err) => {
// handle error response
});
});

关于javascript - 使用 Airtable.js 时如何从 done() 回调返回数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50108966/

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