我有一个从Web服务检索数据的Zapier触发器(app)。 Web服务以500个项目为单位返回数据,每个项目包含一个UNIX时间戳,Web服务参数('since')指定要检索的数据块的开始时间。
为了使其工作,我需要按顺序检索数据块,在前一个块中检索的数据允许我找到下一个Web服务调用的“since”值。
我目前使用的代码:
const fetchItems = (z, bundle, since) => {
return z.request({
url: URL_PATH + ':' + URL_PORT + '/v1/items',
params: {
since: since
}
}).then(( response) => {
if (response.status === 401) {
throw new Error('The authentication has expired.');
} else if (response.status !== 200){
throw new Error('Status ' + response.status + ' returned.');
}
return response.json;
});
};
const processItems = (z, bundle) => {
var jsonAll = [];
var since = 0;
var jsonLength = ITEM_BLOCK_SIZE;
return (function loop(i) {
if (jsonLength === ITEM_BLOCK_SIZE) {
new Promise((resolve, reject) => {
fetchTransactions(z, bundle, since).then((json) => {
since = json[json.length - 1].modified;
jsonLength = json.length;
for (j = 0; j < json.length; j++) {
jsonAll.push( json[j]);
}
resolve();
});
}).then(loop.bind(null, jsonLength));
} else {
return jsonAll;
}
})(0);
}
module.exports = {
...
operation: {
...
perform: processItems,
...
}
};
我遇到的问题是,当我运行此代码时,Zapier会返回以下错误:结果必须是数组,得到:undefined,()
fetchItems()函数工作正常,它返回指定'since'值的数据块。
我在使用承诺方面经验有限,所以我们将不胜感激任何帮助。
答案 0 :(得分:2)
我花了一些时间来解开processItems
的意图,但过了一会儿我就掌握了逻辑。我真的很欣赏IIFE loop
逻辑的简单之美,所以在我的版本中保留了它,但你混淆了一些关于同步和异步代码如何工作的假设(这可能是由于对promises的不熟悉)。
const processItems = (z, bundle) => {
const jsonAll = [];
let since = 0;
return new Promise((resolve, reject) => {
(function loop() {
console.log("inLoop");
fetchTransactions(z, bundle, since)
.then(json => {
const jsonLength = json.length;
since = json[json.length - 1].modified;
jsonAll.push(...json);
if (jsonLength === ITEM_BLOCK_SIZE) {
loop(jsonLength);
} else {
resolve(jsonAll);
}
})
.catch(reject);
})();
});
};
// Testdriver (proves it works)
let callCount = 0;
const ITEM_BLOCK_SIZE = 10;
function fetchTransactions() {
return new Promise(resolve => {
if (callCount === 5) return resolve([{ modified: 100 }]);
const list = [];
for (let i = 0; i < ITEM_BLOCK_SIZE; i++) list.push({ modified: 42 });
callCount++;
resolve(list);
});
}
processItems({},{}).then(results =>
console.log(
"results are correct?",
results.length === 5 * ITEM_BLOCK_SIZE + 1
)
);
整个函数是 async 方法,而代码中的任何return
语句当然都是同步。这就是它返回undefined
的原因;函数体执行后很久就会返回返回的值!
这就是Promise
闪耀的地方。您可以从方法中返回Promise
,然后等待稍后完成的承诺。这就是失败的原因:你基本上需要在resolve
函数内返回一个loop
d的Promise。
所以我补充说,删除了我认为是一些不必要的Promise
创建,并将一些全局状态转移到了本地状态。