首页 > 解决方案 > 如何在没有 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.allfunction 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
}

标签: node.jsfor-looppromise

解决方案


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: ");
}

这是一般的想法:

  1. 创建一个共享函数,因为两者checkPhotos()几乎checkVideos()都在做同样的事情。
  2. 使用 request-promise 而不是 request 模块,因为它返回一个 promise,这使得协调多个异步操作变得更加容易。
  3. 配置 request-promise 以返回整个响应对象,以便可以像使用 request 一样使用它
  4. 过滤掉不返回 403 的结果,因为您的原始代码仅在请求状态为 403 的情况下将某些内容放入结果数组中。这对我来说似乎不是特别安全(例如 404 怎么样),但这是您的原始代码正在做。
  5. 用于.map()轻松生成一系列承诺。
  6. 用于Promise.all()知道整个 Promise 数组何时全部解决。

附言

  1. 您的分析功能也需要重写。它的逻辑是不正确的。
  2. Promise.all()期望您将单个参数传递给它,该参数是一组 promises
  3. 您正在传递一个context变量,但没有使用它。

推荐阅读