繁体   English   中英

在nodejs中进行多次调用

[英]Make multiple calls in nodejs

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

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

现在我的任务是按名称对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内容。

请帮我解决一下这个。

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

或者声明你的函数async并做

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

使用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);
}) ;

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

更改saveToFIle函数,如下所示。 您也可以使用支持fs库的promise,比如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并以正确的方式对boook进行排序

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

你有没有考虑过以不同的方式看待这个问题? 如果其他API会出现这种情况,我会考虑在聚合器服务或API本身聚合这些API(如果可以的话)。

最好一次接收所需的所有数据而不是多次呼叫,这将导致延迟和复杂性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM