Asynchronous Promise and Async/Await may be the most complete introductory guide
Tips: This article is the most complete introduction to the asynchronous promise and Async/Await blogs, which are original and self transforming. Welcome to communicate with the front-end experts and point out any issues
1、 Why is there Async/Await?
We all know that Promise's solution already exists, why should ES7 propose a new Async/Await standard?
The answer is actually obvious: Although Promise breaks out of the strange circle of asynchronous nesting and is expressed more clearly in chain form, we also found that when there are a large number of asynchronous requests and the process is complex, we will find them filled with screens, which looks very difficult. The emergence of Async/Await in ES7 is to solve this complex situation.
Firstly, we must understand Promise.
2、 Promise Introduction
2.1 Promise Example
What is Promise, and many people should know the basic concepts? Take a look directly at the following code (the examples in the entire article are based on the setDelaySecond and setDelay functions, please remember):
Const setDelay=(millisecond)=>{
Return new Promise (resolve, reject)=>{
If (typeof millisecond!='number ') reject (new Error ('parameter must be of type number');
SetTimeout()=>{
Resolve (output after I delayed ${millisecond} milliseconds)
}Millisecond
})
}
We encapsulate a Promise in a function and return a Promise, which is more standardized.
You can see that the defined Promise has two parameters, resolve and reject.
Resolve: Transforms asynchronous execution from pending (request) to resolving (successful return), which is a function execution return.
Reject: As the name suggests, 'reject' means changing from a request to a 'failure'. It is a function that can execute and return a result, but we recommend returning an error, 'new Error()'.
For the above example, you can reject ('return a string ') and return it as you please, but we still recommend returning an Error object to make it clearer that it is' failed' and more standardized.
2.2 Promise then and catch
We obtain our return value through Promise's prototype method then:
SetDelay (3000)
. then (result)=>{
Console. log (result)//Output "I output after a delay of 2000 milliseconds"
})
Output the following value: 'I output after a delay of 2000 milliseconds'.
What if something goes wrong? Then use catch to capture:
SetDelay ('I am a string ')
. then (result)=>{
Console. log (result)//No entry
})
. catch ((err)=>{
Console. log (err)//Output error: "Parameter must be of type number"
})
Isn't it very simple? Okay, now I'll increase the difficulty a bit. What would happen if multiple Promises were executed?
2.3 Promise Interdependence
We are writing a promise:
Const setDelaySecond=(seconds)=>{
Return new Promise (resolve, reject)=>{
If (typeof seconds!='number '| | seconds>10) reject (new Error (' parameter must be of type number and less than or equal to 10 ');
SetTimeout()=>{
Console. log (` First, the setDelaySeconds function output was delayed by ${seconds} seconds, resulting in a total delay of ${seconds+2} seconds')
Resolve (setDelay (2000))//This depends on the previous promise
}, seconds * 1000)
})
}
What happens when the next dependent resolve returns another Promise? Let's execute:
setDelaySecond(3).then((result)=>{
console.log(result)
}).catch((err)=>{
console.log(err);
})
Tips: This article is the most complete introduction to the asynchronous promise and Async/Await blogs, which are original and self transforming. Welcome to communicate with the front-end experts and point out any issues
1、 Why is there Async/Await?
We all know that Promise's solution already exists, why should ES7 propose a new Async/Await standard?
The answer is actually obvious: Although Promise breaks out of the strange circle of asynchronous nesting and is expressed more clearly in chain form, we also found that when there are a large number of asynchronous requests and the process is complex, we will find them filled with screens, which looks very difficult. The emergence of Async/Await in ES7 is to solve this complex situation.
Firstly, we must understand Promise.
2、 Promise Introduction
2.1 Promise Example
What is Promise, and many people should know the basic concepts? Take a look directly at the following code (the examples in the entire article are based on the setDelaySecond and setDelay functions, please remember):
Const setDelay=(millisecond)=>{
Return new Promise (resolve, reject)=>{
If (typeof millisecond!='number ') reject (new Error ('parameter must be of type number');
SetTimeout()=>{
Resolve (output after I delayed ${millisecond} milliseconds)
}Millisecond
})
}
We encapsulate a Promise in a function and return a Promise, which is more standardized.
You can see that the defined Promise has two parameters, resolve and reject.
Resolve: Transforms asynchronous execution from pending (request) to resolving (successful return), which is a function execution return.
Reject: As the name suggests, 'reject' means changing from a request to a 'failure'. It is a function that can execute and return a result, but we recommend returning an error, 'new Error()'.
For the above example, you can reject ('return a string ') and return it as you please, but we still recommend returning an Error object to make it clearer that it is' failed' and more standardized.
2.2 Promise then and catch
We obtain our return value through Promise's prototype method then:
SetDelay (3000)
. then (result)=>{
Console. log (result)//Output "I output after a delay of 2000 milliseconds"
})
Output the following value: 'I output after a delay of 2000 milliseconds'.
What if something goes wrong? Then use catch to capture:
SetDelay ('I am a string ')
. then (result)=>{
Console. log (result)//No entry
})
. catch ((err)=>{
Console. log (err)//Output error: "Parameter must be of type number"
})
Isn't it very simple? Okay, now I'll increase the difficulty a bit. What would happen if multiple Promises were executed?
2.3 Promise Interdependence
We are writing a promise:
Const setDelaySecond=(seconds)=>{
Return new Promise (resolve, reject)=>{
If (typeof seconds!='number '| | seconds>10) reject (new Error (' parameter must be of type number and less than or equal to 10 ');
SetTimeout()=>{
Console. log (` First, the setDelaySeconds function output was delayed by ${seconds} seconds, resulting in a total delay of ${seconds+2} seconds')
Resolve (setDelay (2000))//This depends on the previous promise
}, seconds * 1000)
})
}
What happens when the next dependent resolve returns another Promise? Let's execute:
setDelay('2000')
.then((result)=>{
console.log('第一步完成了');
console.log(result)
return setDelaySecond(3)
})
.catch((err)=>{ // 这里移到第一个链式去,发现上面的不执行了,下面的继续执行
console.log(err);
})
.then((result)=>{
console.log('第二步完成了');
console.log(result);
})
惊喜的发现,链式继续走下去了!!输出如下(undefined是因为上一个then没有返回一个Promise):
clipboard.png
重点来了!敲黑板!!链式中的catch并不是终点!!catch完如果还有then还会继续往下走!不信的话可以把第一个catch在最后面的那个例子后面再加几个then,你会发现并不会跳出链式执行。
如果顺序执行setDelay,setDelay1,setDelaySecond,按照上述的逻辑,流程图可以概括如下:
clipboard.png
catch只是捕获错误的一个链式表达,并不是break!
所以,catch放的位置也很有讲究,一般放在一些重要的、必须catch的程序的最后。**这些重要的程序中间一旦出现错误,会马上跳过其他后续程序的操作直接执行到最近的catch代码块,但不影响catch后续的操作!!!!
到这就不得不体一个ES2018标准新引入的Promise的finally,表示在catch后必须肯定会默认执行的的操作。这里不多展开,细节可以参考:Promise的finally
2.5 Promise链式中间想返回自定义的值
其实很简单,用Promise的原型方法resolve即可:
setDelay(2000).then((result)=>{
console.log('第一步完成了');
console.log(result);
let message = '这是我自己想处理的值';
return Promise.resolve(message) // 这里返回我想在下一阶段处理的值
})
.then((result)=>{
console.log('第二步完成了');
console.log(result); // 这里拿到上一阶段的返回值
//return Promise.resolve('这里可以继续返回')
})
.catch((err)=>{
console.log(err);
})
2.7 如何跳出或停止Promise链式
不同于一般的function的break的方式,如果你是这样的操作:func().then().then().then().catch()的方式,你想在第一个then就跳出链式,后面的不想执行了,不同于一般的break;return null;return false等操作,可以说,如何停止Promise链,是一大难点,是整个Promise最复杂的地方。
1.用链式的思维想,我们拒绝掉某一链,那么不就是相当于直接跳到了catch模块吗?
我们是不是可以直接“拒绝“掉达到停止的目的?
setDelay(2000)
.then((result)=>{
console.log(result)
console.log('我进行到第一步的');
return setDelaySecond(1)
})
.then((result)=>{
console.log('我进行到第二步的');
console.log(result);
console.log('我主动跳出循环了');
return Promise.reject('跳出循环的信息') // 这里返回一个reject,主动跳出循环了
})
.then((result)=>{
console.log('我不执行');
})
.catch((mes)=>{
console.dir(mes)
console.log('我跳出了');
})
但是很容易看到缺点:有时候你并不确定是因为错误跳出的,还是主动跳出的,所以我们可以加一个标志位:
return Promise.reject({
isNotErrorExpection: true // 返回的地方加一个标志位,判断是否是错误类型,如果不是,那么说明可以是主动跳出循环的
})
或者根据上述的代码判断catch的地方输出的类型是不是属于错误对象的,是的话说明是错误,不是的话说明是主动跳出的,你可以自己选择(这就是为什么要统一错误reject的时候输出new Error('错误信息')的原因,规范!)
当然你也可以直接抛出一个错误跳出:
throw new Error('错误信息') // 直接跳出,那就不能用判断是否为错误对象的方法进行判断了
2.那有时候我们有这个需求:catch是放在中间(不是末尾),而同时我们又不想执行catch后面的代码,也就是链式的绝对中止,应该怎么办?
我们看这段代码:
setDelay(2000)
.then((result)=>{
console.log(result)
console.log('我进行到第一步的');
return setDelaySecond(1)
})
.then((result)=>{
console.log('我进行到第二步的');
console.log(result);
console.log('我主动跳出循环了');
return Promise.reject('跳出循环的信息') // 这里直接调用Promise原型方法返回一个reject,主动跳出循环了
})
.then((result)=>{
console.log('我不执行');
})
.catch((mes)=>{
console.dir(mes)
console.log('我跳出了');
})
.then((res)=>{
console.log('我不想执行,但是却执行了'); // 问题在这,上述的终止方法治标不治本。
})
这时候最后一步then还是执行了,整条链都其实没有本质上的跳出,那应该怎么办呢?
敲黑板!!重点来了!我们看Promise/A+规范可以知道:
A promise must be in one of three states: pending, fulfilled, or rejected.
Promise其实是有三种状态的:pending,resolve,rejected,那么我们一直在讨论resolve和rejected这2个状态,是不是忽视了pending这个状态呢?pending状态顾名思义就是请求中的状态,成功请求就是resolve,失败就是reject,其实他就是个中间过渡状态。
而我们上面讨论过了,then的下一层级其实得到的是上一层级返回的Promise对象,也就是说原Promise对象与新对象状态保持一致。那么重点来了,如果你想在这一层级进行终止,是不是直接让它永远都pending下去,那么后续的操作不就没了吗?是不是就达到这个目的了??觉得有疑问的可以参考Promise/A+规范。
我们直接看代码:
setDelay(2000)
.then((result)=>{
console.log(result)
console.log('我进行到第一步的');
return setDelaySecond(1)
})
.then((result)=>{
console.log(result);
console.log('我主动跳出循环了');
// return Promise.reject('跳出循环的信息')
// 重点在这
return new Promise(()=>{console.log('后续的不会执行')}) // 这里返回的一个新的Promise,没有resolve和reject,那么会一直处于pending状态,因为没返回啊,那么这种状态就一直保持着,中断了这个Promise
})
.then((result)=>{
console.log('我不执行');
})
.catch((mes)=>{
console.dir(mes)
console.log('我跳出了');
})
.then((res)=>{
console.log('我也不会执行')
})
这样就解决了上述,错误跳出而导致无法完全终止Promise链的问题。
但是!随之而来也有一个问题,那就是可能会导致潜在的内存泄漏,因为我们知道这个一直处于pending状态下的Promise会一直处于被挂起的状态,而我们具体不知道浏览器的机制细节也不清楚,一般的网页没有关系,但大量的复杂的这种pending状态势必会导致内存泄漏,具体的没有测试过,后续可能会跟进测试(nodeJS或webapp里面不推荐这样),而我通过查询也难以找到答案,这篇文章可以推荐看一下:从如何停掉 Promise 链说起。可能对你有帮助在此种情况下如何做。
当然一般情况下是不会存在泄漏,只是有这种风险,无法取消Promise一直是它的痛点。而上述两个奇妙的取消方法要具体情形具体使用。
2.8 Promise.all
其实这几个方法就简单了,就是一个简写串联所有你需要的Promise执行,具体可以参照阮一峰的ES6Promise.all教程。
我这上一个代码例子
Promise.all([setDelay(1000), setDelaySecond(1)]).then(result=>{
console.log(result);
})
.catch(err=>{
console.log(err);
})
// 输出["我延迟了1000毫秒后输出的", "我延迟了1秒后输出的,注意单位是秒"]
输出的是一个数组,相当于把all方法里面的Promise并行执行,注意是并行。
相当于两个Promise同时开始执行,同时返回值,并不是先执行第一个再执行第二个,如果你想串行执行,请参考我后面写的循环Promise循环串行(第4.2小节)。
然后把resolve的值保存在数组中输出。类似的还有Promise.race这里就不多赘述了。
三、Async/await介绍
3.1 基于Promise的Async/await
什么是async/await呢?可以总结为一句话:async/await是一对好基友,缺一不可,他们的出生是为Promise服务的。可以说async/await是Promise的爸爸,进化版。为什么这么说呢?且听我细细道来。
为什么要有async/await存在呢?
前文已经说过了,为了解决大量复杂不易读的Promise异步的问题,才出现的改良版。
这两个基友必须同时出现,缺一不可,那么先说一下Async:
async function process() {
}
上面可以看出,async必须声明的是一个function,不要去声明别的,要是那样await就不理你了(报错)。
这样声明也是错的!
const async demo = function () {} // 错误
必须紧跟着function。接下来说一下它的兄弟await。
上面说到必须是个函数(function),那么await就必须是在这个async声明的函数内部使用,否则就会报错。
就算你这样写,也是错的。
let data = 'data'
demo = async function () {
const test = function () {
await data
}
}
必须是直系(作用域链不能隔代),这样会报错:Uncaught SyntaxError: await is only valid in async function。
讲完了基本规范,我们接下去说一下他们的本质。
3.2 async的本质
敲黑板!!!很重要!async声明的函数的返回本质上是一个Promise。
什么意思呢?就是说你只要声明了这个函数是async,那么内部不管你怎么处理,它的返回肯定是个Promise。
看下列例子:
(async function () {
return '我是Promise'
})()
// 返回是Promise
//Promise {
你会发现返回是这个:Promise {
自动解析成Promise.resolve('我是Promise');
等同于:
(async function () {
return Promise.resolve('我是Promise');
})()
所以你想像一般function的返回那样,拿到返回值,原来的思维要改改了!你可以这样拿到返回值:
const demo = async function () {
return Promise.resolve('我是Promise');
// 等同于 return '我是Promise'
// 等同于 return new Promise((resolve,reject)=>{ resolve('我是Promise') })
}
demo.then(result=>{
console.log(result) // 这里拿到返回值
})
上述三种写法都行,要看注释细节都写在里面了!!像对待Promise一样去对待async的返回值!!!
好的接下去我们看await的干嘛用的.
3.3 await的本质与例子
await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖。
这一句咋一看很别扭,好的不急,我们从例子开始看:
const demo = async ()=>{
let result = await new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('我延迟了一秒')
}, 1000)
});
console.log('我由于上面的程序还没执行完,先不执行“等待一会”');
}
// demo的返回当做Promise
demo().then(result=>{
console.log('输出',result);
})
await顾名思义就是等待一会,只要await声明的函数还没有返回,那么下面的程序是不会去执行的!!!。这就是字面意义的等待一会(等待返回再去执行)。
那么你到这测试一下,你会发现输出是这个:输出 undefined。这是为什么呢?这也是我想强调的一个地方!!!
你在demo函数里面都没声明返回,哪来的then?所以正确写法是这样:
const demo = async ()=>{
let result = await new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('我延迟了一秒')
}, 1000)
});
console.log('我由于上面的程序还没执行完,先不执行“等待一会”');
return result;
}
// demo的返回当做Promise
demo().then(result=>{
console.log('输出',result); // 输出 我延迟了一秒
})
我推荐的写法是带上then,规范一点,当然你没有返回也是没问题的,demo会照常执行。下面这种写法是不带返回值的写法:
const demo = async ()=>{
let result = await new Promise((resolve, reject) => {
setTimeout(()=>{
resolve('我延迟了一秒')
}, 1000)
});
console.log('我由于上面的程序还没执行完,先不执行“等待一会”');
}
demo();
所以可以发现,只要你用await声明的异步返回,是必须“等待”到有返回值的时候,代码才继续执行下去。
那事实是这样吗?你可以跑一下这段代码:
const demo = async ()=>{
let result = await setTimeout(()=>{
console.log('我延迟了一秒');
}, 1000)
console.log('我由于上面的程序还没执行完,先不执行“等待一会”');
return result
}
demo().then(result=>{
console.log('输出',result);
})
你会发现,输出是这样的:
我由于上面的程序还没执行完,先不执行“等待一会”
输出 1
我延迟了一秒
奇怪,并没有await啊?setTimeout是异步啊,问题在哪?问题就在于setTimeout这是个异步,但是不是Promise!起不到“等待一会”的作用。
所以更准确的说法应该是用await声明的Promise异步返回,必须“等待”到有返回值的时候,代码才继续执行下去。
请记住await是在等待一个Promise的异步返回
当然这种等待的效果只存在于“异步”的情况,await可以用于声明一般情况下的传值吗?
事实是当然可以:
const demo = async ()=>{
let message = '我是声明值'
let result = await message;
console.log(result);
console.log('我由于上面的程序还没执行完,先不执行“等待一会”');
return result
}
demo().then(result=>{
console.log('输出',result);
})
Output:
I declare the value
I won't execute 'wait for a moment' because the above program has not been completed yet
Output I am a declared value
Just one thing to note here: then execution is always final.
3.4 Actual combat of async/await advantages
Now let's take a look at the actual combat:
Const setDelay=(millisecond)=>{
Return new Promise (resolve, reject)=>{
If (typeof millisecond!='number ') reject (new Error ('parameter must be of type number');
SetTimeout()=>{
Resolve (output after I delayed ${millisecond} milliseconds)
}Millisecond
})
}
Const setDelaySecond=(seconds)=>{
Return new Promise (resolve, reject)=>{
If (typeof seconds!='number '| | seconds>10) reject (new Error (' parameter must be of type number and less than or equal to 10 ');
SetTimeout()=>{
Resolve (I delayed the output by ${seconds} seconds, please note that the unit is seconds)
}, seconds * 1000)
})
}
For example, the above two delay functions (written above), for example, I want to delay for 1 second first, then delay for 2 seconds, then delay for 1 second, and finally output "complete". This process, if written using then's method, would be like this (nested hell writing without sending when going out and turning right):
SetDelay (1000)
. then (result=>{
Console. log (result);
Return setDelaySecond (2)
})
. then (result=>{
Console. log (result);
Return setDelay (1000)
})
. then (result=>{
Console. log (result);
Console. log ('Done ')
})
. catch (err=>{
Console. log (err);
})
At first glance, isn't it quite complicated? If there is more logic, it may be more tiring to watch. Now let's try async/await
(async()=>{
Const result=await setDelay (1000);
Console. log (result);
Console. log (await setDelaySecond (2));
Console. log (await setDelay (1000));
Console. log ('Completed ');
}) ()
Look! Is there no redundant long chain code, and the semantics are very clear and comfortable? So, when you see this, you must have noticed that the catch above is not implemented in async? Next, let's analyze how async/await handles errors?
3.5 async/await error handling
Because the async function returns a Promise, we can catch errors outside.
Const demo=async()=>{
Const result=await setDelay (1000);
Console. log (result);
Console. log (await setDelaySecond (2));
Console. log (await setDelay (1000));
Console. log ('Completed ');
}
Demo (). catch (err=>{
Console. log (err);
})
Capture errors in the catch of the async function and treat them as a Pormise. If you don't want to use this method, you can use try Catch statement:
(async()=>{
Try{
Const result=await setDelay (1000);
Console. log (result);
Console. log (await setDelaySecond (2));
Console. log (await setDelay (1000));
Console. log ('Completed ');
}Catch (e){
Console. log (e)// Error caught here
}
}) ()
Of course, you don't need to catch outside at this time.
Usually, our try The number of catches will not be too many, but the most. If there are too many, it indicates that your code definitely needs to be refactored, and it must not have been written very well. Another point is try Catch is usually only used when needed, and sometimes it is not necessary to write errors in the catch.
Someone might ask, I try Catch seems to only wrap around code blocks. If I need to split and process them separately, and don't want to crash the entire process due to one error, then should I write a bunch of tries Catch? I'm just uncomfortable, I just don't want to write try What about catch? Here is a great solution for reference only:
We know that the word 'await' must be followed by a promise. Can we write it like this?
(async()=>{
Const result=await setDelay (1000). catch (err=>{
Console. log (err)
});
Console. log (result);
Const result1=await setDelaySecond (12). catch (err=>{
Console. log (err)
})
Console. log (result1);
Console. log (await setDelay (1000));
Console. log ('Completed ');
}) ()
Output in this way:
I delayed the output by 1000 milliseconds
Error: The parameter must be of type number and be less than or equal to 10
At Promise (test4. html: 19)
At new Promise (
At setDelaySecond (test4. html: 18)
At test4. html: 56
Undefined
I delayed the output by 1000 milliseconds
Completed
Is it great that even if there are errors, they won't affect subsequent operations? Of course not, do you think this code is also very ugly? It's messy and awkward to write, and it follows catch. So we can improve by encapsulating the code function that extracts errors:
//To function
Function to (promise){
Return promise. then (data=>{
Return [null, data];
})
. catch (err=>[err])// Return writing for es6
}
The return is an array, with the first being an error and the second being an asynchronous result, using the following:
(async()=>{
//The writing method of ES6 returns an array (if you find it unfamiliar with the writing method of ES5). The first is the error message, and the second is the asynchronous return data of then. It should be noted that duplicate variable declarations may cause problems (for example, if using let or const, please change the variable name).
[err, result]=await to (setDelay (1000))
//If err exists, there is an error, and if you don't want to continue executing, throw an error
If (err) throw new Error ('An error occurred and I no longer want to execute it ');
Console. log (result);
[err, result1]=await to (setDelaySecond (12))
//If you still want to execute, don't throw an error
If (err) console. log ('An error occurred and I want to continue executing ', err);
Console. log (result1);
Console. log (await setDelay (1000));
Console. log ('Completed ');
}) ()
3.6 Asynchronous/await interrupt (termination program)
Firstly, we need to clarify that Promise itself cannot be aborted. Promise itself is just a state machine that stores three states (pending, resolved, rejected). Once a request is made, it must be closed loop and cannot be cancelled. Previously, being in the pending state was only a state of suspending a request, not canceling. This situation is generally not allowed to occur, but is only used to temporarily suspend the chain process.
The essence of interruption (termination) is just hanging in the chain, not essentially canceling the Promise request, which cannot be done, and Promise does not have a cancel state.
Unlike the chain writing method of Promise, it is easy to interrupt a program in async/await because the semantics are very obvious. In fact, just like the general function writing method, when you want to interrupt, you can simply return a value, null, empty, or false. See example:
Let count=6;
Const demo=async()=>{
Const result=await setDelay (1000);
Console. log (result);
Const result1=await setDelaySecond (count);
Console. log (result1);
If (count>5){
Return 'I have exited and will not proceed with the following';
//Return;
//Return false// These writing methods are all acceptable
//Return null;
}
Console. log (await setDelay (1000));
Console. log ('Completed ');
};
Demo (). then (result=>{
Console. log (result);
})
. catch (err=>{
Console. log (err);
})
The essence is to directly return a Promise, which is equivalent to returning Promise. resolve ('I have exited and will not proceed below '). Of course, you can also return a' reject ': return Promise. reject (new Error ('reject'), which will enter the error message.
The async function essentially returns a Promise!
4、 Points to pay attention to during asynchronous operations in actual combat
We often use the two writing methods mentioned above, and may also mix them. Sometimes, we may encounter some situations. Here is an example to illustrate:
4.1 Promise to Obtain Data (Serial) Then Writing Notes
It goes without saying that parallelism is very simple, simply issuing requests through a loop or using Promise. all. What should we do if we need to serialize a request?
We need to implement a program that delays the output values by 1 second in sequence for a total of 5 seconds. Firstly, the Promise loop is relatively cumbersome:
We often make mistakes! Just not valuing the impact of function names and function execution on the program
Let's not talk about loops, let's give an example of an error. Now we have a delay function
Const setDelay=(millisecond)=>{
Return new Promise (resolve, reject)=>{
If (typeof millisecond!='number ') reject (new Error ('parameter must be of type number');
SetTimeout()=>{
Resolve (output after I delayed ${millisecond} milliseconds)
}Millisecond
})
}
We want to achieve the goal of "looping through the serial execution of the Promise function with a delay of one second", and the expected result should be: outputting the output after I delay for 1000 milliseconds every other second, after a total of 3 cycles
syncPromise(arr).then(result=>{
console.log(result);
console.log('ok');
})
//Or add methods to the Promise class
Promise. syncAll=function syncAll(){
Return syncPromise
}//You can use it directly in the future
Promise. syncAll (arr). then (result=>{
Console. log (result);
Console. log ('Completed ');
})
The Great God also summarized a writing method for reduce, which is actually a process of iterating through arrays:
const p = arr.reduce((total, current)=>{
return total.then((result)=>{
console.log(result);
return current()
})
}Promise. resolve ('Program Start ')
p. Then (result)=>{
Console. log ('Finished ', result);
})
Both are feasible in the circular field of Promise.
4.3 async/await loop for obtaining data (serial)
Now let's introduce the practical application of Niubi's async/await. Do you have to look at the above code? Indeed, I also think it's troublesome. So, can there be any improvement if using async/await? This is the meaning of its appearance:
Simulate the loop of the above code:
(async ()=>{
arr = [timeout(2000), timeout(1000), timeout(1000)]
for (var i=0; i < arr.length; i++) {
result = await arr[i]();
console.log(result);
}
})()
... Is that all? Yes... That's it, isn't it particularly convenient!!!! Semanticization is also very obvious!! In order to maintain consistency with the above style, no error handling has been added here, so remember to add your try during actual combat Catch statement to catch errors.
4、 Postscript
I have always wanted to summarize Promise and async/await, but I may not have summarized enough in many aspects. I have tried my best to expand the space, and there may be new knowledge points and summary points that will be updated in the future (to be continued). However, the beginner's level is basically sufficient.
We often say that the emergence of async/await eliminated Promise, which can be said to be a big mistake. On the contrary, it is precisely because of Promise that there is an improved version of async/await. From the above analysis, it can be seen that the two are complementary and indispensable.
To learn async/await well, one must first be proficient in Promise. The two are inseparable, and there are different opinions and suggestions for improvement. Welcome to guide!
Front end white, everyone communicates with each other, peace!