Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 将promiseAll转换为渐进式承诺解决(例如每3个promises)是行不通的_Node.js_Ecmascript 6_Promise_Es6 Promise_Ecmascript 2016 - Fatal编程技术网

Node.js 将promiseAll转换为渐进式承诺解决(例如每3个promises)是行不通的

Node.js 将promiseAll转换为渐进式承诺解决(例如每3个promises)是行不通的,node.js,ecmascript-6,promise,es6-promise,ecmascript-2016,Node.js,Ecmascript 6,Promise,Es6 Promise,Ecmascript 2016,我有一份承诺清单,目前我正在使用promiseAll来解决这些承诺 以下是我目前的代码: const pageFutures = myQuery.pages.map(async (pageNumber: number) => { const urlObject: any = await this._service.getResultURL(searchRecord.details.id, authorization, pageNumber); if (!url

我有一份承诺清单,目前我正在使用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'. 
因此,无论我以何种方式使它工作(我自己的迭代器或任何库),只要我对它有很好的理解,我都可以接受。
如果有人能解释这一点并帮助我摆脱这种困惑,我将不胜感激。

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

事实上,正如我理解你的问题,你想推迟一些DB请求

您不想延迟解析由DB请求创建的
承诺
。。。就像不!别那么做!承诺将在DB返回结果时解决。干扰这个过程是个坏主意

我用你试过的图书馆撞了我的头。。。但是我不能用它来解决你的问题。所以我的想法是循环数据并设置一些超时

我在这里做了一个可运行的演示:

这是代码。注意,我模拟了一些数据和一个DB请求。你必须适应它。您还必须调整超时延迟。整整一秒钟当然太长了

// 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.
//该部分用于模拟要保存的某些数据。
//为了好玩,让我们把它做成一个随机的数量。
让howmount=Math.ceil(Math.random()*20)
//一个假的数据数组。。。
让someData=[]
for(设i=0;i{
log(“请求数据库…”)
返回新承诺(功能(解决、拒绝){
解析(“请求#”+数据迭代器+“完成”);
})
}
//好的,我们都准备好了,开始吧!
让batchSize=3//一次执行的请求量。
让delay=1000//每批之间的延迟。
//循环浏览您拥有的所有数据。
for(设i=0;i{
//用于澄清控制台的空行。
console.log(“”)
//按“batchSize”或更小的值对请求进行分组(如果我们即将完成)。
对于(设j=0;j{
console.log(结果)
//对结果做点什么。
// ...
})
}//如果仍然有数据,则结束。
}//结束发送该批的请求。
},delay*i)//超时延迟。
}//批量结束拆分。
}//每个数据的结束。

首先,您询问了一个关于解决方案尝试失败的问题。该问题称为

事实上,正如我理解你的问题,你想推迟一些DB请求

您不想延迟解析由DB请求创建的
承诺
,就像不!不要尝试那样!承诺将在DB返回结果时解析。干扰该过程是个坏主意

我用你试过的图书馆砸了我的头……但我无法用它解决你的问题。所以我想到了只循环数据并设置一些超时的想法

我在这里做了一个可运行的演示:

这是代码。请注意,我模拟了一些数据和一个DB请求。您必须调整它。您还必须调整超时延迟。一整秒肯定太长了

// 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.
//该部分用于模拟要保存的某些数据。
//为了好玩,让我们把它做成一个随机的数量。
让howmount=Math.ceil(Math.random()*20)
//一个假的数据数组。。。
让someData=[]
for(设i=0;i{
log(“请求数据库…”)
返回新承诺(功能(解决、拒绝){
解析(“请求#”+数据迭代器+“完成”);
})
}
//好的,我们都准备好了,开始吧!
让batchSize=3//一次执行的请求量。
让delay=1000//每批之间的延迟。
//循环浏览您拥有的所有数据。
for(设i=0;i{
//用于澄清控制台的空行。
console.log(“”)
//按“batchSize”或更小的值对请求进行分组(如果我们即将完成)。
对于(设j=0;j{
console.log(结果)
//对结果做点什么。
// ...
})
}//如果仍然有数据,则结束。
}//结束发送该批的请求。
},delay*i)//超时延迟。
}//批量结束拆分。
}//每个数据的结束。
首先请注意:

  • 实际上,在您当前的设置中,数据库可能必须同时处理多个大容量插入。但这种并发性并不是由使用
    Promise.all
    引起的。即使您在代码中省略了
    Promise.all
    ,它仍然会有这种行为。这是因为承诺已经创建,所以数据库也会这样做请求将以任何方式执行

  • 与您的问题无关,但不要使用:当您手中已有承诺时,无需使用
    新承诺创建承诺:
    bulkInsert()
    返回承诺,因此返回该承诺

由于您关心的是数据库负载,我将把
pageFutures
承诺发起的工作限制在非数据库方面:它们不必等待彼此的解决方案,这样代码就可以保持原样

让这些承诺与您当前存储在
对象中的内容解决:您希望插入的数据。然后将所有这些数组连接到一个大数组,并将其馈送到一个数据库
bulkInsert()
调用

下面是它的样子:

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}`,
  });
  // Return here, don't access the database yet...
  return data.objects.filter((object: any) => object.type === "observed-data" 
                                           && object.created);
});
const all: any = await Promise.all(pageFutures).catch(e => {
  console.log(e);
  return []; // in case of error, still return an array
}).flat(); // flatten it, so all data chunks are concatenated in one long array
// Don't create a new Promise with `new`, only to wrap an other promise. 
//   It is an antipattern. Use the promise returned by `bulkInsert`
return this._resultsDatastore.bulkInsert(databaseName, objects);
这使用了相当新的
.flat()
。如果您不支持它,请查看上提供的备选方案。

首先请注意:

  • 实际上,在当前的设置中,数据库可能需要处理多个批量插入