承诺回调和异步/等待
首先,我们必须了解两个主要概念
同步编程
异步编程
同步编程
它等待每个语句完成执行,然后再转到下一条语句。
如果语句不相互依赖,但是由于它们在队列中,它们仍在等待执行,则此方法可能会减慢应用程序的速度。
异步编程
在移动到下一条语句之前,它不等待当前语句完成执行。例如,调用Web服务并使用JavaScript执行文件复制。
调用Web服务可能需要一些时间才能返回结果,同时我们可以完成其他一些操作。
服务器提供结果后,我们无需等待就可以对其进行处理。
我们的三种方法1.回调2.承诺3.异步/等待处理异步编程。
回调
const articles = [ {title:'First article'}, {title:'Second article'} ]; function getArticles(){ setTimeout(()=>{ let articleContent=''; articles.forEach((article,index)=>{ articleContent+=`${article.title}`+` `; }); console.log(articleContent); },1000); }; getArticles();
在这里,我们仅创建了一个商品数组,并在1秒钟后打印在控制台上。
将setTimeout函数与1秒时间配合使用只是为了展示服务器行为。
现在,如果我们通过另一个功能将新文章添加到上述列表中,该怎么办
function createArticle(article){ setTimeout(()=>{ articles.push(article); },2000); }
如果我们现在先用新文章先调用createArticle,然后再用getArticle进行调用,那么我们应该获得三篇文章,但是只有前两篇文章
const articles = [ {title:'First article'}, {title:'Second article'} ]; function getArticles(){ setTimeout(()=>{ let articleContent=''; articles.forEach((article,index)=>{ articleContent+=`${article.title}`+` `; }); console.log(articleContent); },1000); }; function createArticle(article){ setTimeout(()=>{ articles.push(article); },2000); } createArticle({title:'Third article'}); getArticles(); //控制台输出 "First article Second article "
为什么会这样呢?
因为createArticle的执行有2秒的超时,与此同时getArticle完成了执行
示例
const articles = [ {title:'First article'}, {title:'Second article'} ]; function getArticles(){ setTimeout(()=>{ let articleContent=''; articles.forEach((article,index)=>{ articleContent+=`${article.title}`+` `; }); console.log(articleContent); },1000); }; function createArticle(article, callback){ setTimeout(()=>{ articles.push(article); callback(); },2000); } createArticle({title:'Third article'},getArticles); //控制台输出 "First article Second article Third article "
我们使用回调将getArticle的调用嵌套在createArticle中。
请注意,将getArticles作为参数传递给createArticle函数。但是这样,嵌套回调变得复杂
承诺
通过使用promises,我们不需要传递回调函数。承诺有两个论点:解决和拒绝。如果函数成功执行,我们可以调用resolve()
其他函数reject()
const articles = [ {title:'First article'}, {title:'Second article'} ]; function getArticles(){ setTimeout(()=>{ let articleContent=''; articles.forEach((article,index)=>{ articleContent+=`${article.title}`+` `; }); console.log(articleContent); },1000); }; function createArticle(article){ return new Promise((resolve,reject)=>{ articles.push(article); let isError=false; if(!isError){ resolve(); } else { reject(); } }); } createArticle({title:'Third article'}) .then(getArticles()); //控制台输出 "First article Second article Third article " handling error with promises: const articles = [ {title:'First article'}, {title:'Second article'} ]; function getArticles(){ setTimeout(()=>{ let articleContent=''; articles.forEach((article,index)=>{ articleContent+=`${article.title}`+` `; }); console.log(articleContent); },1000); }; function createArticle(article){ return new Promise((resolve,reject)=>{ articles.push(article); let isError=true; if(!isError){ resolve(); }else{ reject('Something went wrong'); } }); } createArticle({title:'Third article'}) .then(getArticles()) .catch(error=>console.log(error)); //控制台输出 "Something went wrong"
我们从createArticle调用reject并捕获了错误
全部承诺
const promise1=Promise.resolve('Hello'); const promise2=100; const promise3=new Promise((resolve,reject)=>{ setTimeout(resolve,2000,'test'); }); Promise.all([promise1,promise2,promise3]) .then((values)=>console.log(values)); //控制台输出 ["Hello", 100, "test"]
我们可以将诺言合并到一个数组中,然后使用实际的then语句,而不是在每个诺言之后嵌套then语句
我们可以使用jsonplaceholder的fetchapi
const promise0=fetch('https://jsonplaceholder.typicode.com/users').then(res=>res.json()); const promise1=Promise.resolve('Hello'); const promise2=100; const promise3=new Promise((resolve,reject)=>{ setTimeout(resolve,2000,'test'); }); Promise.all([promise0,promise1,promise2,promise3]) .then((values)=>console.log(values));
异步/等待
要使用awaiton语句,该功能应标记为异步
<!DOCTYPE html> <html> <head> <title>Async/Await Example</title> </head> <body> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <script type="text/babel"> const articles = [ {title:'First article'}, {title:'Second article'} ]; function getArticles(){ setTimeout(()=>{ let articleContent=''; articles.forEach((article,index)=>{ articleContent+=`${article.title}`+` `; }); console.log(articleContent); },1000); } function createArticle(article){ articles.push(article); } async function testAsync(){ await createArticle({title:'Third article'}); getArticles(); } testAsync(); //控制台输出 //第一篇第二篇第三篇 </script> </body> </html>
testAsync函数被标记为异步,并且我们使用了等待createArticle函数来首先完成它。然后我们打电话给getArticles()
。
使用async/await是Promise的更好版本,并使代码更简洁