Record the callback functions (asynchronous and synchronous problems) encountered by arr.map and arr.foreach

Time:2021-5-8

The general question is:
Through the callback function of map or foreach loop, the array is operated,There are Ajax asynchronous functions inside the callback function, which are called by await synchronous writing. The array printed by console.log is always inconsistent with the page actually rendered to the view layer.
It’s just a for loop.

So to sum up, the basic knowledge is not deep enough in understanding the API of map and foreach, and the use scenarios of await keywords are not thorough (although it is a for loop, the scope function can find the top-level function scope, so no error will be reported)

Post code:

error code

adBannerList.map(async (item) => {
  //How to write asynchronous function to synchronous function
  let res = await this.getAliyunAds();
  //After the asynchronous function is executed successfully, change the value of this array
  item.imageUrl = res.imgUrl;
  item.linkUrl = res.actUrl;
})
//At the end of the map loop, bidirectional binding is performed
this.setData({
  bannerList: adBannerList,
});
console.log('bannerList', this.data.bannerList)

The expected result is that the bidirectional binding SetData function will not be executed until the end of the map loop.
The actual result is that SetData is executed before the map loop is finished (before the asynchronous function after the internal await is finished).

Let’s find out about async await
Later, for information:Await is a way to write asynchronous to synchronous, but it does not block the synchronous code of the main thread, it only blocks the asynchronous code
But look at the following code:

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
 
async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}
 
asyncPrint('hello world', 3000);
//Hello World (printed after 3S)

So:

In async statements, synchronous and await asynchronous codes are not distinguished by the event loop event mode (that is, there is no synchronous and asynchronous operation)Asynchronous code and synchronous code with await are regarded as synchronous code, which is executed from top to bottom in synchronous blocking mode

Back to the point:
Advanced loop traversal functions such as foreach and map cannot change the internal item object while looping(After the map is changed, a new array is returned, and foreach is the original array that has been changed)。
The difference between foreach and for loop is recommended
The difference between for and foreach
At this time, the result seen by the console.log array is inconsistent with the result rendered by view rendering.
Here, we need to have a deep understanding of the reference type and simple type of console. Log, as well as the mechanism of console. Log.
I recommend reading this articlePit encountered by console.log

Correct code:

for(let i = 0;i < adBannerList.length; i++) {
  let item = adBannerList[i]
  //The await keyword can be used here because there is no function scope inside the for loop,
  //So we will look up the function scope, as long as there is async.
  let res = await this.getAliyunAds();
  item.imageUrl = res.imgUrl;
  item.linkUrl = res.actUrl;
}

this.setData({
  bannerList: adBannerList,
});

Summary of knowledge points:
1. The callback function of map and foreach (there should be more similar functions) is a synchronous function, not an asynchronous function.

Knowledge points to be promoted:
1. The mechanism of console.log. Especially for reference types
2. The loop function mechanism of type map and foreach.

As for why the for loop can solve my business problems, I haven’t fully understood.
As a matter of fact, when inquiring about the information, Ruan Yifeng introduced async await with an example
I said something like that. Only when it is used in practical work, can we really grasp the knowledge points after rollover and try to understand why?
If readers know how to explain why for and foreach can satisfy my business, please leave a message.

Examples of excerpts from Ruan Yifeng’s chapter:
The following code can also solve my problem. In fact, it’s nothing more than changing my target array in order after successful interface requests.

async function dbFuc(db) {
  let docs = [{}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = await Promise.all(promises);
  console.log(results);
}
//Or use the following notation 
async function dbFuc(db) {
  let docs = [{}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = [];
  for (let promise of promises) {
    results.push(await promise);
  }
  console.log(results);
}

reference:
Ruan Yifeng’s async await method
Explain async await

Recommended Today

Mongodb aggregate

  https://www.cnblogs.com/wt7018/p/11929359.html Mongodb aggregate   1、 Foundation 1. What is aggregation? Aggregation is an aggregation pipeline based on data processing. Each document passes through a pipeline composed of multiple stagesIt can group and filter the pipelines in each stage, and then output the corresponding results after a series of processing DB. Set name. Aggregate ({pipeline: […]