首页 > 解决方案 > 将 promiseAll 转换为渐进式 promise 解决(例如每 3 个promises)不起作用

问题描述

我有一个承诺列表,目前我正在使用 promiseAll 来解决它们

这是我现在的代码:

   const pageFutures = myQuery.pages.map(async (pageNumber: number) => {
      const urlObject: any = await this._service.getResultURL(searchRecord.details.id, authorization, pageNumber);
      if (!urlObject.url) {
        // throw error
      }
      const data = await rp.get({
        gzip: true,
        headers: {
          "Accept-Encoding": "gzip,deflate",
        },
        json: true,
        uri: `${urlObject.url}`,
      })

      const objects = data.objects.filter((object: any) => object.type === "observed-data" && object.created);
      return new Promise((resolve, reject) => {
        this._resultsDatastore.bulkInsert(
          databaseName,
          objects
        ).then(succ => {
          resolve(succ)
        }, err => {
          reject(err)
        })
      })
    })
    const all: any = await Promise.all(pageFutures).catch(e => {
       console.log(e)
     }) 

因此,正如您在这里看到的,我使用 promise all 并且它有效:

const all: any = await Promise.all(pageFutures).catch(e => {
   console.log(e)
 }) 

但是我注意到它会影响数据库性能,所以我决定一次解决每 3 个问题。为此,我正在考虑不同的方法,例如 cwait、异步池或编写我自己的迭代器,但我对如何做到这一点感到困惑?

例如,当我使用 cwait 时:

let promiseQueue = new TaskQueue(Promise,3);
const all=new Promise.map(pageFutures, promiseQueue.wrap(()=>{}));

我不知道要在包装内传递什么,所以我现在通过 ()=>{} 加上我得到

Property 'map' does not exist on type 'PromiseConstructor'. 

因此,无论我如何让它工作(我自己的迭代器或任何库),只要我对它有很好的理解,我都可以接受。如果有人能阐明这一点并帮助我摆脱这种困惑,我将不胜感激?

标签: node.jsecmascript-6promisees6-promiseecmascript-2016

解决方案


首先,您问了一个关于失败的解决方案尝试的问题。这就是所谓的X/Y 问题

所以事实上,据我了解你的问题,你想延迟一些数据库请求。

您不想延迟解决Promise数据库请求创建的...就像不!不要这样尝试!当数据库返回结果时,承诺将得到解决。干扰该过程是个坏主意。

我用你尝试的图书馆撞了一会儿......但我无法解决你的问题。所以我想到了循环数据并设置一些超时的想法。

我在这里做了一个可运行的演示:Delaying DB request in small batch

这是代码。请注意,我模拟了一些数据和数据库请求。你将不得不适应它。您还必须调整超时延迟。一整秒肯定太长了。

// That part is to simulate some data you would like to save.

// Let's make it a random amount for fun.
let howMuch = Math.ceil(Math.random()*20)

// A fake data array...
let someData = []
for(let i=0; i<howMuch; i++){
  someData.push("Data #"+i)
}

console.log("Some feak data")
console.log(someData)
console.log("")

// So we have some data that look real. (lol)
// We want to save it by small group

// And that is to simulate your DB request.
let saveToDB = (data, dataIterator) => {
  console.log("Requesting DB...")
  return new Promise(function(resolve, reject) {
    resolve("Request #"+dataIterator+" complete.");
  })
}

// Ok, we have everything. Let's proceed!
let batchSize = 3 // The amount of request to do at once.
let delay = 1000  // The delay between each batch.

// Loop through all the data you have.
for(let i=0;i<someData.length;i++){

  if(i%batchSize == 0){
    console.log("Splitting in batch...")

    // Process a batch on one timeout.
    let timeout = setTimeout(() => {

      // An empty line to clarify the console.
      console.log("")

      // Grouping the request by the "batchSize" or less if we're almost done.
      for(let j=0;j<batchSize;j++){

        // If there still is data to process.
        if(i+j < someData.length){

          // Your real database request goes here.
          saveToDB(someData[i+j], i+j).then(result=>{
            console.log(result)
            // Do something with the result.
            // ...
          })

        } // END if there is still data.

      } // END sending requests for that batch.

    },delay*i)  // Timeout delay.

  } // END splitting in batch.

} // END for each data.

推荐阅读