Сделайте несколько звонков в nodejs - PullRequest
4 голосов
/ 13 июня 2019

У меня есть некоторые фиктивные данные для менее чем 2 URL:

1. Get the list of users from 'https://myapp.com/authors'.
2. Get the list of Books from 'https://myapp.com/books'.

Теперь моя задача - отсортировать Книги по имени и записать отсортированный список в файл mysortedbooks.json как JSON

Затем мне нужно создать массив авторов со свойством books, в котором есть все книги этого автора.

Если у автора нет книг, этот массив должен быть пустым.В этом случае сортировка не требуется, и данные должны храниться в файле authorBooks.json в формате JSON.

Теперь я должен вернуть обещание, которое разрешается после выполнения вышеуказанных шагов.Например, я должен вернуть последний вызов saveToFile в приведенном ниже коде.

const fs = require('fs');

function getFromURL(url) {
    switch (url) {
        case 'https://myapp.com/authors':
            return Promise.resolve([
                { name: "Chinua Achebe", id: "1" },
                { name: "Hans Christian Andersen", id: "2" },
                { name: "Dante Alighieri", id: "3" },
            ]);
        case 'https://myapp.com/books':
            return Promise.resolve([
                { name: "Things Fall Apart", authorId: "1" },
                { name: "The Epic Of Gilgamesh", authorId: "1" },
                { name: "Fairy tales", authorId: "2" },
                { name: "The Divine Comedy", authorId: "2" },
                { name: "One Thousand and One Nights", authorId: "1" },
                { name: "Pride and Prejudice", authorId: "2" },
            ]);
    }
}

const outFile = fs.createWriteStream('...out-put-path...');

function saveToFile(fileName, data) {
    outFile.write(`${fileName}: ${data}\n`);

    return Promise.resolve();
}


function processData() {
    const authors = getFromURL('https://myapp.com/authors').then(author => {
        return authors;
    });

    const books = getFromURL('https://myapp.com/authors').then(books => {
        return books.sort();
    });

    return saveToFile('mysortedbooks.json', JSON.stringify(books)).then(() => {
        const authorAndBooks = authors.map(author => {
            var jsonData = {};
            jsonData['name'] = author.name;
            jsonData['books'] = [];
            for(var i=0; i<books.length; i++) {
                if(authod.id == books[i].authorId) {
                    jsonData['books'].push(books[i].name);
                }
            }
        });

        saveToFile('authorBooks.json', authorAndBooks);
    });
}

processData().then(() => outFile.end());

Основная логика, которую я должен реализовать, заключается в методе processData.

Я попытался добавить код для решения требования, но застрял, как вернуть promise после всех операций.Также, как создать мой authorAndBooks контент JSON.

Пожалуйста, помогите мне с этим.

Ответы [ 4 ]

6 голосов
/ 13 июня 2019
const authors = getFromURL('https://myapp.com/authors').then(author => {
    return authors;
});

const books = getFromURL('https://myapp.com/authors').then(books => {
    return books.sort();
});

//authors and books are both promises here, so await them
return Promise.all([authors, books]).then(function(results){
    authors = results[0];
    books = results[1];
    return saveToFile(...);
});

альтернативно объявите вашу функцию асинхронной и выполните

const authors = await getFromURL('https://myapp.com/authors').then(author => {
    return authors;
});

const books = await getFromURL('https://myapp.com/authors').then(books => {
    return books.sort();
});

return await saveToFile(...);
0 голосов
/ 23 июля 2019

Рассматривали ли вы посмотреть на это по-другому?Если это будет иметь место для других API, я бы подумал об агрегировании этих API в сервисе агрегатора или самом API, если вы можете.

Всегда лучше получать все данные, которые вам нужны сразувместо нескольких звонков, вы будете нести задержки и сложности.

0 голосов
/ 22 июля 2019

много ошибок в вашем коде.Я постараюсь объяснить один за другим, читать комментарии между кодами.Я бы порекомендовал вам прочитать некоторые основы файловых операций и обещаний.Проблема в вашем методе saveToFile и в том, как вы объединяете обещания в методе processData.

Измените функцию saveToFIle следующим образом.Вы также можете использовать обещание, поддерживающее библиотеки fs, такие как fs-extra, но я не уверен, хотите ли вы использовать внешнюю библиотеку.

const path = require('path');     
const basePath = '.';//whatever base path of your directories    
function saveToFile(fileName, data) {
// fs.writeFile method uses callback, you can use many ways to convert a callback method to support promises
// this is one of the simple and doesn't require any libraries to import
   return new Promise((resolve,reject)=>{
        let filePath = path.join(basePath,fileName);
        return fs.writeFile(filePath,data,(err, data)=>{
            if(err) reject(err);
          else resolve();
        });
    })
}

Теперь измените вашу функцию processData на использование promise.all и правильно сортируйте буки

function processData() {
    let books, authors;
    //Promise.all can be used when operations are not interdependent, fteches result fasetr as works like parallel requests
    return Promise.all([
        getFromURL('https://myapp.com/books'),
        getFromURL('https://myapp.com/authors')
    ]).then(data => {
        books = data[0];
        authors = data[1];
        let authorAndBooks = authors.map(author => {
            let jsonData = {};
            jsonData['name'] = author.name;
            jsonData['books'] = [];
            for(var i=0; i<books.length; i++) {
                if(author.id == books[i].authorId) {
                    jsonData['books'].push(books[i].name);
                }
            }
            return jsonData;
            console.log(jsonData);
        });
         // you will have to use a comparator to sort objects, given below it will sort books based on names.
         books.sort((first,second)=>{ return first.name>second.name ?1:-1})
        return Promise.all([
        saveToFile("mysortedbooks.json",JSON.stringify(books)),
        saveToFile("authorBooks.json",JSON.stringify(authorAndBooks))])
    }).then(data=>{
        console.log('All operations complete');
    }) 
}

processData();
0 голосов
/ 21 июля 2019

Рефакторинг кода с помощью Promise Chaining и для создания нескольких файловых потоков

const fs = require('fs');

function getFromURL(url) {
    switch (url) {
        case 'https://myapp.com/authors':
            return Promise.resolve([
                { name: "Chinua Achebe", id: "1" },
                { name: "Hans Christian Andersen", id: "2" },
                { name: "Dante Alighieri", id: "3" },
            ]);
        case 'https://myapp.com/books':
            return Promise.resolve([
                { name: "Things Fall Apart", authorId: "1" },
                { name: "The Epic Of Gilgamesh", authorId: "1" },
                { name: "Fairy tales", authorId: "2" },
                { name: "The Divine Comedy", authorId: "2" },
                { name: "One Thousand and One Nights", authorId: "1" },
                { name: "Pride and Prejudice", authorId: "2" },
            ]);
    }
}

function saveToFile(fileName, data) {
    const outFile = fs.createWriteStream(`/var/${fileName}`);
    outFile.write(data);
    return Promise.resolve(outFile);
}

function authorBookMapping(data) {
    let [authors, books] = data;
    var jsonData = {};            
    authors.map(author => {
        jsonData['name'] = author.name;
        jsonData['books'] = [];
        for(var i=0; i<books.length; i++) {
            if(author.id == books[i].authorId) {
                jsonData['books'].push(books[i].name);
            }
        }
    });
    return {
        books: books,
        authorAndBooks: jsonData
    };  
}

function writeFile(data) {
    if(data) {
        const {books, authorAndBooks} = data;
        const book = saveToFile('mysortedbooks.json', JSON.stringify(books));
        const author = saveToFile('authorBooks.json', JSON.stringify(authorAndBooks));
        return Promise.all([book, author]);
    }    
}


function processData() {            

        const authors = getFromURL('https://myapp.com/authors');

        const books = getFromURL('https://myapp.com/authors');

        return Promise.all([authors, books])
                .then(authorBookMapping)
                .then(writeFile)                
}

processData().then((stream) => {
    for(let s in stream) {
        stream[s].close();
    }
})
.catch((err) => {
    console.log("Err :", err);
}) ;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...