首页 > 其他分享 >Promise

Promise

时间:2023-07-01 14:12:30浏览次数:36  
标签:异步 console log JavaScript 任务 Promise

Promise

前端的异步运行机制

JavaScript作为单线程运行于浏览器之中,这是每本JavaScript教科书中都会被提到的。同时出于对UI线程操作的安全性考虑,JavaScript和UI线程也处于同一个线程中。因此对于耗时的操作,将会阻塞UI的响应。为了更好的UI体验,应该尽量的避免JavaScript中执行较长耗时的操作(如大量for循环的对象diff等)或者是长时间I/O阻塞的任务。所以在浏览器中的大多数任务都是异步(无阻塞)执行的,例如:鼠标点击事件、窗口大小拖拉事件、定时器触发事件、Ajax完成回调事件等。当每一个异步事件完成时,它都将被放入一个叫做“浏览器事件队列”的事件池中去。而这些被放在事件池中的任务,将会被JavaScript引擎单线程的一个一个的处理,当在此次处理中再次遇见的异步任务,它们也会被放到事件池中去,等待下一次的tick被处理。另外在HTML5中引入了新的组件-Web Worker,它可以在JavaScript线程以外执行这些任务,而不阻塞当前UI线程。

浏览器中的事件循环模型如下图所示:

browser-event-base

MainLoop-单线程

由于浏览器的这种内部事件循环机制,所以JavaScript一直以callback回调的方式来处理事件任务。因此无所避免的对于多个的JavaScript异步任务的处理,将会遇见callback hell(回调地狱),使得这类代码及其不可读和难易维护。

asyncTask1(data, function (data1){
    asyncTask2(data1, function (data2){
        asyncTask3(data2, function (data3){
                // .... 魔鬼式的金字塔还在继续
        })
    })
})

为了解决这种回调地狱问题Promise就诞生了

Promise对象

Promise/A+规范

  • Promise对象有三种状态: Pending– Promise对象的初始状态,等待任务的完成或者被拒绝;Fulfilled– 任务执行完成并且成功的状态;Rejected– 任务执行完成并且失败的状态
  • Promise的状态只可能从Pending状态转到Fulfilled状态或者Rejected状态,而且不能逆向转换,同时Fulfilled状态和Rejected状态也不能相互转换
  • Promise对象必须实现then方法,thenpromise规范的核心,而且then方法也必须返回一个Promise对象,同一个Promise对象可以注册多个then方法,并且回调的执行顺序跟它们的注册顺序一致
  • then方法接受两个回调函数,它们分别为:成功时的回调和失败时的回调;并且它们分别在:Promise由Pending状态转换到Fulfilled状态时被调用和在Promise由Pending状态转换到Rejected状态时被调用

可以表示为下图

流程图

错误处理

myPromise
  .then(handleFulfilledA)
  .then(handleFulfilledB)
  .then(handleFulfilledC)
   // 如果以上那一个then出现错误,则会跳过其它的then处理,直接跳到catch中进行处理
  .catch(handleRejectedAny)

多个异步任务的串行处理

我们可以将上面回调地狱的代码转换成如下

asyncTask1(data)
    .then(data1 =>{
        return asyncTask2(data1);
    })
    .then(data2 => {
       return asyncTask3(data2);
    })
    // 仍然可以继续then方法

Promise将原来回调地狱中的回调函数,从横向式增加巧妙的变为了纵向增长。以链式的风格,纵向的书写,使得代码更加的可读和易于维护。

对于解决这类异步任务的方式,在ES7中将会引入async、await两个关键字,以同步的方式来书写异步的任务,它被誉为JavaScript异步处理的终极方案。这两个关键字是ES6标准中生成器(generator)和Promise的组合新语法,内置generator的执行器的一种方式。当然async、await的讲解并不会在本文中展开,有兴趣的读者可以参见MDN资料

多个异步任务的并行处理

在有些场景下,我们所要处理的多个异步任务之间并没有像上例中的那么强的依赖关系,只需要在这一系列的异步任务全部完成的时候执行一些特定逻辑

myPromise.all([
    http.get('/demo1'),
    http.get('/demo2'),
    http.get('/demo3')
])
.then(function(results){
    console.log('result 1', results[0])
    console.log('result 2', results[1])
    console.log('result 3', results[2])
})

获取最先完成的

多个任务同时进行,只获取最先返回结果

myPromise.race([
    http.get('/demo1'),
    http.get('/demo2'),
    http.get('/demo3')
])
.then(result => {
    console.log('result = ', results)
})

async/await异步函数

这其实是一个语法糖

// 定义了一个返回Promise的函数
function add(a:number, b:number): Promise<number>{
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            return resolve(a+b)
        }, 2000)
    })
}


async function call(){
    try{
        // 使用await 可以直接获取Promise的返回值类似相当于写在then中
        const a = await add(2,4)
        console.log(a)
    }catch(err){
        // 异常处理
        console.log(err)
    }
}


async function call(){
    // await 可以直接加在Promise前面,变量就能接收到them里面的返回值了
    const [a,b] = await Promise.all([add(1,2), add(3,6)])
    console.log(a,b)
}

call()

标签:异步,console,log,JavaScript,任务,Promise
From: https://www.cnblogs.com/wdszh/p/17519042.html

相关文章

  • 来看一个人才对Promise的讲解
     我承若在女朋友生日那天给她买一个lv包包,如果生日那天isForget则resolve这个包(成功返回),反之则抛出一个错误:我加班去了,忘记了   ......
  • js promise对象数组,使用reduce序列化执行
    自己使用mdn官方例子测试了一下,发现还有一些小问题,调试了一下OK了。consttimeOut=function(ms){ returnnewPromise(function(resolve){ returnsetTimeout(resolve,ms); })}varp1=function(){ returnnewPromise(function(resolve){ console.log(newDate()+'......
  • await/async/Promise
    await关键字:在JavaScript中,await关键字用于等待一个异步函数的完成,并暂停当前函数的执行,直到异步函数返回一个解决的值(resolvedvalue)或被拒绝的原因(rejectedreason)。await关键字只能在async函数内部使用。使用await时,需要将其放置在一个返回Promise的异步函数前面,并使用await......
  • promise
    1.处理异步有哪些方式在计算机编程中,处理异步操作的方式有多种。下面是一些常见的处理异步的方式:回调函数(CallbackFunctions):这是一种传统的处理异步操作的方式。在这种模式下,可以将一个函数作为参数传递给异步操作,当操作完成时,调用该函数进行后续处理。这种方式简单直接,但容......
  • 回调函数、Promise、Generator 函数和async
    看了几篇文章,受益匪浅,写几个demo看下理解是否正确:文章链接:Generator函数的含义与用法-阮一峰的网络日志(ruanyifeng.com)  async函数的含义和用法-阮一峰的网络日志(ruanyifeng.com)回调函数<script>//----------------------------回调函数-------------------......
  • 在JavaScript中实现Promise对象
    classPromise2{#status='pending'constructor(fn){this.q=[]constresolve=(data)=>{this.#status='fulfilled'constf1f2=this.q.shift()if(!f1f2||!f1f2[0])returnconstx=f1f2[0].ca......
  • 【JS基础】Promise.resolve()
    Promise.resolve 静态方法将给定值“解析”为Promise。 如果值是Promise,则返回该Promise;如果值是thenable,返回的Promise会“跟随”这个thanable的对象,采用它的最终状态;否则,返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。 注意:不要在解析......
  • promise、async、await
    一、promise语法上:promise是一个对象,从它可以获取异步操作的消息本意上:它是承诺,承诺它过一段时间会给你一个结果【如果想通过异步方法先后检测用户名和密码,需要先异步检测用户名,然后再异步检测密码的情况下就很适合Promise】1、创建此构造函数包含一个参数和一个带有resolv......
  • Promise解决并发请求和async/await解决并发请求
    有的时候会出现一种情况,就是你需要调用多次API,因为可能调一次返回的数据量过大,占满了带宽就直接卡死,但是你又不想每次只调用一个,想每次调用多个,你就可以尝试下面的方法:使用Promise解决并发问题functionasyncconcurrentRequests(args,len=10){constrecordArr=0//......
  • promise.all简易实现
    functionall(arr){returnnewPromise((resolve,reject)=>{letrtnArr=[]letcount=0for(leti=0;i<arr.length;i++){Promise.resolve(arr[i]).then(res=>{rtnArr[i]=rescount+=1count......