Как решить тревожные циклы и обещания без асинхронного ожидания - PullRequest
0 голосов
/ 13 февраля 2019

Я борюсь с циклами и обещаниями без использования async / await (это не было доступно в версии функций Azure, которые я запускал изначально, и я еще не перенес весь свой код в более новую версию). Я проверяю свою базу данныхна json-файлах, внутри каждого json-файла, который я проверяю, действительны ли URL-адреса, содержащиеся в 2 разных массивах.Затем, если срок действия URL истек, я хочу вставить этот идентификатор json в контейнер, чтобы иметь дело с последующим обновлением / update.

В настоящее время я пытаюсь проверить 2 отдельных массива на каждый json.

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
}

1 Ответ

0 голосов
/ 14 февраля 2019

Вот фиксированная версия 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: ");
}

Вот общая идея:

  1. Создать совместно используемую функцию, так как checkPhotos() и checkVideos() в значительной степени делают то же самое.
  2. Используйте запрос-обещание вместо модуля запроса, потому что он возвращает обещание, облегчающее координацию нескольких асинхронных операций.
  3. Настройка запроса-обещания длявернуть весь объект ответа, чтобы его можно было использовать так же, как вы использовали запрос
  4. Отфильтровать результаты, которые не возвращают 403, поскольку ваш исходный код только помещал что-то в массив результатов, если статус запроса был 403Мне это не кажется особенно безопасным (как в случае с 404), но именно этим занимался ваш исходный код.
  5. Используйте .map() для простой генерации массива обещаний.
  6. Используйте Promise.all(), чтобы узнать, когда весь массив обещаний будет разрешен.

PS

  1. Ваша функция анализа также должна быть переписана.Его логика неверна.
  2. Promise.all() ожидает, что вы передадите ему единственный аргумент, представляющий собой массив обещаний .
  3. Вы передаете contextпеременная вокруг, но не использующая его.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...