簡體   English   中英

不使用 async/await 的 reduce() function 中的異步性

[英]Asyncronicity in a reduce() function WITHOUT using async/await

我正在修補 exec() function 以允許在 ZCCADCDEDB567ABAE643E15DCF0974E503Z 中進行子填充,這就是為什么我無法在此處使用async/await的原因——我的 function 沒有機會在鏈上取消等待它在子模塊本身中,我無法在異步 function 本身之外添加async/await

有了這個,讓我們看看我想要做什么。 我有兩個單獨的 arrays ( matchingMealPlanFoodsmatchingMealPlanRecipeFoods ),里面裝滿了我需要填充的 ID。 它們都駐留在同一個數組中,即foods 它們每個都需要一個帶有聚合的數據庫調用,而我當前場景中的問題是只有一個 arrays 填充,因為它們是異步發生的。

我現在要做的是使用reduce function 將更新后的 foods 數組返回到下一次reduce運行,這樣當返回最終結果時,我可以在我的doc上替換整個foods數組。 問題當然是,當reduce function 進入下一次運行時,我的aggregate/exec還沒有返回值。 有沒有一種方法可以在沒有async/await的情況下實現這一點? 我在這里包含了高級結構,這樣您就可以看到需要發生什么,以及為什么使用.then()可能不可行。

編輯:使用異步建議更新代碼

function execute(model, docs, options, lean, cb) {
  options = formatOptions(options);
  let resolvedCount = 0;
  let error = false;

  (async () => {
    for (let doc of docs) {
      let newFoodsArray = [...doc.foods];
      for (let option of options) {
        const path = option.path.split(".");
        // ... various things happen here to prep the data
        const aggregationOptions = [
          // // $match, then $unwind, then $replaceRoot
        ];

        await rootRefModel
          .aggregate(aggregationOptions)
          .exec((err, refSubDocuments) => {
            // more stuff happens
            console.log('newFoodsArray', newFoodsArray); // this is to check whether the second iteration is using the updated newFoods Array
            const arrToReturn = newFoodsArray.map((food) => {
              const newMatchingArray = food[nests[1]].map((matchingFood) => {
                //more stuff
                return matchingFood;
              });

              const updatedFood = food;
              updatedFood[`${nests[1]}`] = newMatchingArray;
              return updatedFood;
            });
            console.log('arrToReturn', arrToReturn);
            newFoodsArray = [...arrToReturn];
          });
      }
    };
    console.log('finalNewFoods', newFoodsArray); // this should log after the other two, but it is logging first.
    const document = doc.toObject();
    document.foods = newFoodsArray;

    if (resolvedCount === options.length) cb(null, [document]);
  }
})()

編輯:因為它似乎會有所幫助,所以這就是我在上面摘錄的調用execute function 的內容。

 /**
   * This will populate sub refs
   * @param {import('mongoose').ModelPopulateOptions[]|
   * import('mongoose').ModelPopulateOptions|String[]|String} options
   * @returns {Promise}
   */
  schema.methods.subPopulate = function (options = null) {
    const model = this.constructor;
    if (options) {
      return new Promise((resolve, reject) => execute(model, [this], options, false, (err, docs) => {
        if (err) return reject(err);
        return resolve(docs[0]);
      }));
    }
    Promise.resolve();
  };
};

我們可以在這里使用 async/await 就好了,只要我們記住async和“返回一個 Promise”是一樣的, await和“resolving a Promise's.then or.catch”是一樣的。

因此,讓我們將所有這些“同步但基於回調”的調用轉換為可等待對象:您的外部代碼必須繼續遵守 API 合約,但由於它並不意味着返回值,我們可以安全地將我們自己的版本標記為async ,然后我們可以在我們自己的代碼中將await與任何其他基於回調的 function 調用結合使用,就好了:

async function execute(model, docs, options, lean, andThenContinueToThis) {
  options = formatOptions(options);
  let option, resolvedCount = 0;

  for (let doc of docs) {
    let newFoodsArray = [...doc.foods];

    for (option of options) {
      // ...things happen here...

      const aggregationOptions = [/*...data...*/];

      try {
        const refSubDocuments = await new Promise((resolve, reject) => rootRefModel
          .aggregate(aggregationOptions)
          .exec((err, result) => err ? reject(err) : resolve(result));
        // ...do some work based on refSubDocuments...
      }

      // remember to forward errors and then stop:
      catch (err) {
        return andThenContinueToThis(err);
      }
    }

    // remember: bind newFoodsArray somewhere so it doesn't get lost next iteration
  }

  // As our absolutely last action, when all went well, we trigger the call forwarding:
  andThenContinueToThis(null, dataToForward);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM