【解決方法】どのリクエストが最初に送信されたかに従って、複数の API レスポンスを注文するにはどうすればよいですか? javascript/nodejs で

プログラミングQA


こんにちは, 私は改善したいプロジェクトに取り組んでいます. このアップグレードのアイデアがありました. そして, API から短時間に複数回リクエストしています. ここでの問題は. どうすればどのリクエストが最初に送信されたかに応じて応答しますか? 詳細、私のコードはここで複数回リクエストします にとって ループ:

JavaScript
var queue = [];

function Request(text) {

  console.log(text);
  async function Test(){
  await Api.request(); //This is an example and not a real API request function
  let result = Api.response //
  var URL = result.Object();
      queue.push(URL);  
      var I = queue.shift();
      console.log(I)
  }
  Test()
}

for (Something) { // Yet again and example here.
  
    setTimeout(function() {
      Request(text);
}, 2000);
}

これは、for ループ ルールに従って複数回 API から要求するコードです。このため、実際の API 関数などではなく、例として明確にしました…

のルールとしましょう にとって ここでのループにより、API が 3 つの応答を返すようになります

Response1 // Took 1 second to respond
Response3 // Took 1.5 seconds to respond
Response2 // Took 2 seconds to respond

応答がそれに応じて順序付けられていないことに注意してください. また, それらはランダム化されています. なぜなら, Response3 は Response2 よりも速い可能性があり, 例は続く….

もちろん、APIに依存する各応答は、他の応答よりも早く/遅くなることがあります。これがここで問題を引き起こし、ここでの私の質問は次のとおりです。

この応答が以前/後で来たが、最初の要求に属していることをどのように知ることができますか。また、他の 2 つの要求にも同じことが言えます。

Request1: Response 1 // Took 1 second to respond
Request2: Response 2 // Took 2 seconds to respond
Request3: Response 3 // Took 1.5 seconds to respond

応答 3 が応答 2 の前に来たとしても、コードが応答 2 が応答 3 の前に来るのを待たなければならないかどうかは問題ではありません。

これが意味を成したことを願っています。下手な英語で申し訳ありません。 前もって感謝します。

(編集):私が達成しようとしていることを説明するのは難しすぎるので、ここに私のコードの実際の部分を投稿します:

var text = "How's work this week? | It's been pretty good not going to lie. It has been a pretty decent day as well, I like how everything is going this week, |  I hope it get's better."
const API  = require('SomeApiWrapperLibrary.js');
var queue = [];
async function processText(text) {

    var Object1 = "Something"
    const Rw = new Api.Client({
        usernameOrEmail: "something",
        password: "somethingelse"
    });
    async function Test(){
      console.log(text);
    await Rw.start(); //required
    let result = await Rw.makeTTS(voice, text);
    var URL = result.Object();
        queue.push( text + " : " + URL);         // queue is now [URL]
        var I = queue.shift();
        console.log(I)
    }
    Test()
}


const prefix = ' | ';

const splitText = text.split(prefix);

async function Request(){

for (const text of splitText) {


 await processText(text).then(console.log('Done'))

  
}

}
Request()

私が試したこと:

ここで試したのは、ここでわかるように、キューにプッシュされている応答を数値化することです。

JavaScript
var queue = []; 

var Number = 0;

function Request(text) {

  console.log(text);
  async function Test(){
  await Api.request(); //This is an example and not a real API request function
  let result = Api.response //
  Number++
  var URL = result.Object();
      queue.push( "URL " + Number + URL);  
      var I = queue.shift();
      console.log(I)
  }
  Test()
}

for (Something) { // Yet again and example here.
  
    setTimeout(function() {
      Request(text);
}, 2000);
}

しかし、それは完全に間違っています ここの数字は常に 1 から 3 までです. たとえ 2 番目の応答が 1 番目の応答になるはずだったとしても. それでも 2 と呼ばれます.

解決策 1

あなたはそうしない。 API リクエストは、処理して結果を返すまでにかかる時間の長さが異なる場合があります。 すべてのリクエストは他のすべてのリクエストとは独立して処理され、他のリクエストが存在することすら認識していません。

リクエストが行われたのと同じ順序で結果を返したい場合は、一度に 1 つずつリクエストを行い、それぞれが返されるのを待ってから次のリクエストを行う必要があります。

解決策 2

解決策 1 のコメントで述べたように、最初の要求が完了するのを待ってから 2 番目の要求を開始する必要はありません。 2 番目の要求を処理する前に、最初の要求が完了するまで待つ必要があります。

私は保存する傾向があります Promise オブジェクト[^] キューで。 次に、それらを処理するときに、次のことを行う必要があります。 await 彼ら。

例えば:

JavaScript
class PromiseQueue {
    #queue = [];
    enqueue(promise) {
        this.#queue.push(promise);
    }
    [Symbol.asyncIterator]() {
        return {
            queue: this.#queue,
            async next() {
                if (this.queue.length === 0) {
                    return { done: true };
                }
                
                const promise = this.queue.shift();
                const value = await promise;
                return { done: false, value };
            }
        };
    }
}

// Just for an example - returns a promise which will resolve with the given state after a specified delay:
const waitFor = async (ms, result) => new Promise(resolve => setTimeout(() => resolve(result), ms));

(async () => {
    const taskQueue = new PromiseQueue();
    console.time("TaskQueue");
    
    taskQueue.enqueue(waitFor(2000, "Task 1"));
    taskQueue.enqueue(waitFor(1000, "Task 2"));
    
    for await (let result of taskQueue) {
        console.log(result);
    }
    
    console.timeEnd("TaskQueue");
})();

この例では、「タスク 1」「タスク 2」が順に出力され、合計所要時間は 2 秒以上のタッチです。 最初のタスクが完了するのを待ってから 2 番目のタスクを開始した場合、合計時間は 3 秒をわずかに超えることになります。

コメント

タイトルとURLをコピーしました