简体   繁体   English

在 JavaScript 中同步调用 REST API

[英]Synchronously call a REST API in JavaScript

I am new to JavaScript and the npm world.我是 JavaScript 和 npm 世界的新手。 I try to upload some data to my REST service via a REST post call.我尝试通过 REST 后调用将一些数据上传到我的 REST 服务。 These data I fetch from a csv file.我从 csv 文件中获取这些数据。 So far so good.到现在为止还挺好。 On each fetched line I convert the data (for my needs) and call the REST API for uploading those.在每个提取的行上,我转换数据(根据我的需要)并调用 REST API 来上传这些数据。 Since I have many line (approx. 700) the API gets called quite often consecutively.由于我有很多行(大约 700 行),因此 API 经常被连续调用。 After some calls (guess 500 or so) I get an Socket error经过一些电话(猜测 500 左右)后,我收到一个 Socket 错误

events.js:136
      throw er; // Unhandled 'error' event
      ^

Error: connect ECONNRESET 127.0.0.1:3000
    at Object._errnoException (util.js:999:13)
    at _exceptionWithHostPort (util.js:1020:20)
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1207:14)

I guess this is because I call the REST API to often.我想这是因为我经常调用 REST API。 What I don't understand is: How should I make the call synchronously in order to avoid so many connections?我不明白的是:我应该如何同步进行调用以避免这么多连接? Or should't I?还是我不应该? What would be the proper solution in JS for this?为此,JS 中的正确解决方案是什么?

I have tried with Promises and so on but all this didn't helped but moved the issue some function calls priorly...我已经尝试过 Promises 等等,但所有这些都没有帮助,但之前将问题移到了一些函数调用......

This is my code:这是我的代码:

readCsv()

function readCsv() {
    var csvFile = csvFiles.pop()
    if (csvFile) {
        csv({ delimiter: ";" }).fromFile(csvFile).on('json', async (csvRow) => {
            if (/.*\(NX\)|.*\(NI\)|.*\(NA\)|.*\(WE\)|.*\(RA\)|.*\(MX\)/.test(csvRow["Produkt"])) {
                var data = await addCallLog(
                    csvRow["Datum"],
                    csvRow["Zeit"],
                    csvRow["Menge-Zeit"],
                    csvRow["Zielrufnummer"],
                    csvRow["Produkt"]);
            }
        }).on('done', (error) => {
            //console.log('end')
            readCsv()
        })
    } else {

    }
}

function addCallLog(date, time, duration, number, product) {
    return new Promise(resolve => {
        args.data = { number: number, name: "", timestamp: getTimestamp(date, time), duration: getDuration(duration), type: "OUTGOING" }
        client.methods.addCallLog(args, (data, response) => {
            // client.methods.getCallLog((data, response) => {
            //     console.log(data)
            // })
            //console.log("addCallLog resolve")
            resolve(data)
        })
    })
}

As you can see I had the same issue with reading more than one csv files in parallel.如您所见,我在并行读取多个 csv 文件时遇到了同样的问题。 I solved this by calling recursively the readCsv function and pop the next file after the other when the file read was done.我通过递归调用 readCsv 函数解决了这个问题,并在文件读取完成后弹出下一个文件。

You can't call things synchronously.您不能同步调用事物。 But, you can sequence the async REST calls which is what I presume you mean.但是,您可以对异步 REST 调用进行排序,这就是我认为您的意思。

A problem here is that await addCallLog() won't keep the next json events from being generated so you will end with a zillion requests in flight at the same time and apparently you have so many that you run out of resources.这里的一个问题是await addCallLog()不会阻止生成下一个json事件,因此您将同时以无数个请求结束,而且显然您有太多资源耗尽。

One way around that is to collect the rows you want into an array and then use a regular for loop to iterate that array and you can use await sucessfully in the for loop.一种解决方法是将您想要的行收集到一个数组中,然后使用常规for循环来迭代该数组,您可以在for循环中成功使用await Here's what that would look like:这就是它的样子:

readCsv()

function readCsv() {
    var csvFile = csvFiles.pop()
    if (csvFile) {
        let rows = [];
        csv({ delimiter: ";" }).fromFile(csvFile).on('json', (csvRow) => {
            if (/.*\(NX\)|.*\(NI\)|.*\(NA\)|.*\(WE\)|.*\(RA\)|.*\(MX\)/.test(csvRow["Produkt"])) {
                rows.push(csvRow);
            }
        }).on('done', async (error) => {
            for (let csvRow of rows) {
                var data = await addCallLog(
                    csvRow["Datum"],
                    csvRow["Zeit"],
                    csvRow["Menge-Zeit"],
                    csvRow["Zielrufnummer"],
                    csvRow["Produkt"]
                );
            }
            readCsv();
        })
    } else {

    }
}

function addCallLog(date, time, duration, number, product) {
    return new Promise(resolve => {
        args.data = { number: number, name: "", timestamp: getTimestamp(date, time), duration: getDuration(duration), type: "OUTGOING" }
        client.methods.addCallLog(args, (data, response) => {
            // client.methods.getCallLog((data, response) => {
            //     console.log(data)
            // })
            //console.log("addCallLog resolve")
            resolve(data)
        })
    })
}

Your coding appears to be missing error handling.您的编码似乎缺少错误处理。 The client.methods.addCallLog() needs a way to communicate back an error. client.methods.addCallLog()需要一种方法来传达错误信息。

You probably also need a error event handler for the csv iterator.您可能还需要一个用于 csv 迭代器的error事件处理程序。

After filling the buffer in a prev.在上一页填充缓冲区后。 function I check that buffer for data and upload those one by one using the "then" callback of the promise函数我检查该缓冲区的数据并使用承诺的“then”回调一一上传

var callLogBuffer = []

checkForUpload()

function checkForUpload() {
    console.log("checkForUpload")
    if (callLogBuffer.length > 0) {
        addCallLog(callLogBuffer.pop()).then((data) => {
            checkForUpload()
        })
    }
}


function addCallLog(callLog) {
    return new Promise(resolve => {
        args.data = { number: callLog.number, name: "", timestamp: getTimestamp(callLog.date, callLog.time), duration: getDuration(callLog.duration), type: "OUTGOING" }
        client.methods.addCallLog(args, (data, response) => {
            // client.methods.getCallLog((data, response) => {
            //     console.log(data)
            // })
            //console.log("addCallLog resolve")
            resolve(data)
        })
    })
}

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

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