在Node.js中进行多个调用

时间:2019-06-13 14:02:59

标签: javascript node.js

我有以下2个URL的一些模拟数据:

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

现在我的任务是按名称对“书籍”进行排序,并将排序后的列表以JSON格式写入文件mysortedbooks.json

然后,我必须创建一个具有books属性的作者数组,其中包含该作者的所有书籍。

如果作者没有书籍,则此数组应为空。在这种情况下,不需要排序,数据应以JSON格式存储在文件authorBooks.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 个答案:

答案 0 :(得分:2)

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(...);

答案 1 :(得分:0)

带有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);
}) ;

答案 2 :(得分:0)

您的代码中有很多错误。我将尝试一一解释,阅读代码之间的注释。我建议您阅读一些文件操作和Promise的基础知识。问题出在您的saveToFile方法以及如何在processData方法中链接promise。

如下更改您的saveToFIle函数。您还可以使用Promise支持fs-extra之类的fs库,但是我不确定是否要使用外部库。

2d

现在更改您的processData函数以使用promise.all并以正确的方式对书进行排序

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();
        });
    })
}

答案 3 :(得分:0)

您是否考虑过以其他方式看待这个问题?如果其他API会出现这种情况,我会考虑将这些API聚合到聚合服务中,或者如果可以的话,将API本身聚合。

总是最好一次接收所有数据,而不是多次调用,否则会导致延迟和复杂性。