如何解决麻烦的for循环和承诺没有异步/等待
我正在努力争取循环和承诺,而不使用async / await(这在我最初运行的azure函数版本上不可用,我还没有将我的所有代码转移到更新的版本)我在json文件上检查我的数据库在每个json中,我想看看2个不同数组中包含的URL是否仍然有效。然后,如果url已过期,我想将该json id推入容器以处理稍后/更新。
目前我正在努力尝试每个json测试2个独立的数组。
module.exports = function(context, req) {
getJsons(context, function(res) {
createContainer(context, res)
});
}
function getJsons(context, callback) {
context.log('start');
client.queryDocuments(
collectionUrlJsons,
`SELECT * FROM r`
).toArray((err, results) => {
if (err) {
context.log(err);
context.done();
} else {
context.log(results.length + " jsons");
// now I have all JSONs in an array
analyse(context, results, function(result) {
callback(result);
})
}
});
}
function analyse(context, results) {
var editArr = [];
for (i = 0; i < results.length; i++) {
var arr = [];
var loopPhotos = checkPhotos(context, results[i].photos);
var loopVideos = checkVideos(context, results[i].videos);
Promise.all([loopPhotos, checkVideos]).then(function(result) {
if (result[0].length > 0) {
context.log('photos expired')
arr.push('photo');
}
if (result[1].length > 0) {
context.log('videos expired')
arr.push('video');
}
});
if (arr.length > 0) {
editArr.push(results[i].id);
}
}
return Promise.all(editArr);
}
function checkPhotos(context, photos) {
var arr = [];
for (i = 0; i < photos.length; i++) {
var link = photos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("photo: " + body);
}
});
}
return Promise.all(arr);
}
function checkVideos(context, videos) {
var arr = [];
context.log(videos)
for (i = 0; i < videos.length; i++) {
var link = videos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("video: " + body);
}
});
}
return Promise.all(arr);
}
function createContainer(context, jsons) {
//code
}
编辑下面反映评论 - 将if (arr.length >0)
放入Promise.all
的function analyse
:
module.exports = function(context, req) {
getJsons(context, function(res) {
createContainer(context, res)
});
}
function getJsons(context, callback) {
context.log('start');
client.queryDocuments(
collectionUrlJsons,
`SELECT * FROM r`
).toArray((err, results) => {
if (err) {
context.log(err);
context.done();
} else {
context.log(results.length + " jsons");
// now I have all JSONs in an array
analyse(context, results, function(result) {
callback(result);
})
}
});
}
function analyse(context, results) {
var editArr = [];
for (i = 0; i < results.length; i++) {
var arr = [];
var loopPhotos = checkPhotos(context, results[i].photos);
var loopVideos = checkVideos(context, results[i].videos);
Promise.all([loopPhotos, checkVideos]).then(function(result) {
if (result[0].length > 0) {
context.log('photos expired')
arr.push('photo');
}
if (result[1].length > 0) {
context.log('videos expired')
arr.push('video');
}
if (arr.length > 0) {
editArr.push(results[i].id);
}
});
}
return Promise.all(editArr);
}
function checkPhotos(context, photos) {
var arr = [];
for (i = 0; i < photos.length; i++) {
var link = photos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("photo: " + body);
}
});
}
return Promise.all(arr);
}
function checkVideos(context, videos) {
var arr = [];
context.log(videos)
for (i = 0; i < videos.length; i++) {
var link = videos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("video: " + body);
}
});
}
return Promise.all(arr);
}
function createContainer(context, jsons) {
//code
}
回答如下:
这是checkPhotos()
和checkVideos()
的固定版本:
const rp = require('request-promise');
// returns promise that resolves to an array of 403 messages
// urls that don't respond with 403 don't put anything in the array
function checkUrls(context, urls, msg) {
const promises = urls.map(item => {
return rp({
uri: item.latestUrl,
simple: false,
resolveWithFullResponse: true}
).then(response => {
if (response.statusCode == 403) {
return msg + response.body;
} else {
return null;
}
});
});
return Promise.all(promises).then(data => {
// remove null results from array
return data.filter(item => item !== null);
});
}
// returns promise that resolves to an array
function checkPhotos(context, photos) {
return checkUrls(context, photos, "photo: ");
}
// returns promise that resolves to an array
function checkVideos(context, videos) {
return checkUrls(context, photos, "video: ");
}
这是一般的想法:
- 创建一个共享函数,因为
checkPhotos()
和checkVideos()
几乎都在做同样的事情。 - 使用request-promise而不是request模块,因为它返回一个promise,这样可以更容易地协调多个异步操作。
- 配置request-promise以返回整个响应对象,以便它可以像使用请求一样使用
- 过滤掉不返回403的结果,因为如果请求状态为403,原始代码只会在结果数组中放置一些东西。这对我来说似乎不太安全(就像404那样),但这就是你的原始代码正在做。
- 使用
.map()
轻松生成一系列承诺。 - 使用
Promise.all()
知道什么时候整个承诺都解决了。
附:
- 您的分析功能也需要重写。它的逻辑不正确。
Promise.all()
希望你传递一个承诺数组的参数。- 你传递了一个
context
变量,但没有使用它。
如何解决麻烦的for循环和承诺没有异步/等待
我正在努力争取循环和承诺,而不使用async / await(这在我最初运行的azure函数版本上不可用,我还没有将我的所有代码转移到更新的版本)我在json文件上检查我的数据库在每个json中,我想看看2个不同数组中包含的URL是否仍然有效。然后,如果url已过期,我想将该json id推入容器以处理稍后/更新。
目前我正在努力尝试每个json测试2个独立的数组。
module.exports = function(context, req) {
getJsons(context, function(res) {
createContainer(context, res)
});
}
function getJsons(context, callback) {
context.log('start');
client.queryDocuments(
collectionUrlJsons,
`SELECT * FROM r`
).toArray((err, results) => {
if (err) {
context.log(err);
context.done();
} else {
context.log(results.length + " jsons");
// now I have all JSONs in an array
analyse(context, results, function(result) {
callback(result);
})
}
});
}
function analyse(context, results) {
var editArr = [];
for (i = 0; i < results.length; i++) {
var arr = [];
var loopPhotos = checkPhotos(context, results[i].photos);
var loopVideos = checkVideos(context, results[i].videos);
Promise.all([loopPhotos, checkVideos]).then(function(result) {
if (result[0].length > 0) {
context.log('photos expired')
arr.push('photo');
}
if (result[1].length > 0) {
context.log('videos expired')
arr.push('video');
}
});
if (arr.length > 0) {
editArr.push(results[i].id);
}
}
return Promise.all(editArr);
}
function checkPhotos(context, photos) {
var arr = [];
for (i = 0; i < photos.length; i++) {
var link = photos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("photo: " + body);
}
});
}
return Promise.all(arr);
}
function checkVideos(context, videos) {
var arr = [];
context.log(videos)
for (i = 0; i < videos.length; i++) {
var link = videos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("video: " + body);
}
});
}
return Promise.all(arr);
}
function createContainer(context, jsons) {
//code
}
编辑下面反映评论 - 将if (arr.length >0)
放入Promise.all
的function analyse
:
module.exports = function(context, req) {
getJsons(context, function(res) {
createContainer(context, res)
});
}
function getJsons(context, callback) {
context.log('start');
client.queryDocuments(
collectionUrlJsons,
`SELECT * FROM r`
).toArray((err, results) => {
if (err) {
context.log(err);
context.done();
} else {
context.log(results.length + " jsons");
// now I have all JSONs in an array
analyse(context, results, function(result) {
callback(result);
})
}
});
}
function analyse(context, results) {
var editArr = [];
for (i = 0; i < results.length; i++) {
var arr = [];
var loopPhotos = checkPhotos(context, results[i].photos);
var loopVideos = checkVideos(context, results[i].videos);
Promise.all([loopPhotos, checkVideos]).then(function(result) {
if (result[0].length > 0) {
context.log('photos expired')
arr.push('photo');
}
if (result[1].length > 0) {
context.log('videos expired')
arr.push('video');
}
if (arr.length > 0) {
editArr.push(results[i].id);
}
});
}
return Promise.all(editArr);
}
function checkPhotos(context, photos) {
var arr = [];
for (i = 0; i < photos.length; i++) {
var link = photos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("photo: " + body);
}
});
}
return Promise.all(arr);
}
function checkVideos(context, videos) {
var arr = [];
context.log(videos)
for (i = 0; i < videos.length; i++) {
var link = videos[i].latestUrl;
request(link, function(error, response, body) {
if (response.statusCode == 403) {
arr.push("video: " + body);
}
});
}
return Promise.all(arr);
}
function createContainer(context, jsons) {
//code
}
回答如下:
这是checkPhotos()
和checkVideos()
的固定版本:
const rp = require('request-promise');
// returns promise that resolves to an array of 403 messages
// urls that don't respond with 403 don't put anything in the array
function checkUrls(context, urls, msg) {
const promises = urls.map(item => {
return rp({
uri: item.latestUrl,
simple: false,
resolveWithFullResponse: true}
).then(response => {
if (response.statusCode == 403) {
return msg + response.body;
} else {
return null;
}
});
});
return Promise.all(promises).then(data => {
// remove null results from array
return data.filter(item => item !== null);
});
}
// returns promise that resolves to an array
function checkPhotos(context, photos) {
return checkUrls(context, photos, "photo: ");
}
// returns promise that resolves to an array
function checkVideos(context, videos) {
return checkUrls(context, photos, "video: ");
}
这是一般的想法:
- 创建一个共享函数,因为
checkPhotos()
和checkVideos()
几乎都在做同样的事情。 - 使用request-promise而不是request模块,因为它返回一个promise,这样可以更容易地协调多个异步操作。
- 配置request-promise以返回整个响应对象,以便它可以像使用请求一样使用
- 过滤掉不返回403的结果,因为如果请求状态为403,原始代码只会在结果数组中放置一些东西。这对我来说似乎不太安全(就像404那样),但这就是你的原始代码正在做。
- 使用
.map()
轻松生成一系列承诺。 - 使用
Promise.all()
知道什么时候整个承诺都解决了。
附:
- 您的分析功能也需要重写。它的逻辑不正确。
Promise.all()
希望你传递一个承诺数组的参数。- 你传递了一个
context
变量,但没有使用它。