node.js - 如何在没有 async/await 的情况下解决麻烦的 for 循环和 Promise
问题描述
我在不使用 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()
这是and的固定版本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 以返回整个响应对象,以便可以像使用 request 一样使用它
- 过滤掉不返回 403 的结果,因为您的原始代码仅在请求状态为 403 的情况下将某些内容放入结果数组中。这对我来说似乎不是特别安全(例如 404 怎么样),但这是您的原始代码正在做。
- 用于
.map()
轻松生成一系列承诺。 - 用于
Promise.all()
知道整个 Promise 数组何时全部解决。
附言
- 您的分析功能也需要重写。它的逻辑是不正确的。
Promise.all()
期望您将单个参数传递给它,该参数是一组 promises。- 您正在传递一个
context
变量,但没有使用它。
推荐阅读
- javascript - preact createPortal 多次渲染
- svg - SVG 固定大小的元素在 Viewbox 内相对定位
- python - 与 `top` 相比,tracemalloc.get_traced_memory 显示大约 1/10 的内存使用量
- azure-devops - How to Tag a branch Automatically in Azure DevOps using extension (Tag/Branch Git On Release)
- javascript - '不能在模块外使用 import 语句'与 ES6 Node v.12
- highcharts - ShadowOptionsObject 示例
- java - 如何通过适配器将图像数组传递给 NewActivity
- c++ - 未评估上下文中的函数模板实例化
- haskell - 无法摆脱 reflex-dom 中的递归
- html - NUXTJS | 第一次调用加载 css / layout 时出错