Home >Web Front-end >JS Tutorial >One article will help you master Promise easily

One article will help you master Promise easily

青灯夜游
青灯夜游forward
2023-02-10 19:49:162292browse

One article will help you master Promise easily

In front-end js learning, the most uncomfortable thing for everyone is asynchronous problem. To solve asynchronous, callback hell and other problems, you must learn promises. For most front-end For programmers, promises are simply a nightmare. This article is from an easy-to-understand perspective as an entry point to help everyone easily master promises

Asynchronous Programming


If you want to learn promises, you must understand what asynchronous programming is! As we all know, the js language is a single-threaded mechanism. The so-called single thread means executing in order, executing one task before executing the next one. However, it does not affect the existence of two operations: Synchronous and Asynchronous . These two operations actually do things on an assembly line (single thread), but these two operations are performed in a single thread. The order of execution is just different! When js triggers an asynchronous task, the asynchronous task will be handed over to the browser for processing. When the execution results, the callback function of the asynchronous task will be inserted into the end of the queue to be processed!

Let’s explain our asynchronous in a popular way: Asynchronous is to launch a sub-thread from the main thread to complete the task . Each task has one or more callback functions (callback ), After the previous task ends, instead of executing the next task, the callback function is executed. The latter task is executed without waiting for the previous task to end, so the execution of the program The order is inconsistent with the order of tasks and is asynchronous.

One article will help you master Promise easily

This picture is taken from Asynchronous Programming in Rookie Tutorial Section helps everyone better understand what asynchronous is!

Callback function


The definition of a callback function is very simple: a function is treated as a The actual parameters are passed to another function (external function), and this function is called within the external function to complete certain tasks. It’s called Callback function

Two ways to write the callback function (The effect is the same):

const text = () => {
	   document.write('hello james')
}
setTimeout(text,1000)
setTimeout(()=>{
	   document.write("hello james")
},1000)

In this code setTimeout is a process that takes a long time. Its first parameter is a callback function, and the second parameter is number of milliseconds. After this function is executed A child thread will be generated, the child thread will wait for 1 second, and then execute the callback function "text", and output hello james

setTimeout will be in the child thread in the text Wait for 1 second, but the operation of the main thread will not be affected! For example, the following code:

setTimeout(()=>{
    document.write("hello davis")
},1000)
console.log('123456');

will be printed here first 123456(main thread), and then hello will be output in the text one second later davis(subthread)

callback hell


The word callback hell It sounds very high-end. Before you want to get in touch with Promise, you must understand what callback hell is and why callback hell occurs?
Let’s take a look at the concept first: When a callback function nests a callback function, a nested structure will appear. If there are too many nested functions, callback hell will occur.
For example:
For example, we send three ajax requests:

  • The first one is sent normally
  • The second one is sent The request requires a certain value from the result of the first request as a parameter
  • The third request requires a certain value from the result of the second request as a parameter

You will see the following code:

$.ajax({
  url: '我是第一个请求',
  type: 'get',
  success (res) {
    // 现在发送第二个请求
    $.ajax({
      url: '我是第二个请求',
      type:'post',
      data: { a: res.a, b: res.b },
      success (res1) {
        // 进行第三个请求
        $.ajax({
          url: '我是第三个请求',
          type:'post',
          data: { a: res1.a, b: res1.b },
                  success (res2) { 
            console.log(res2) 
          }
        })
      }
    })
  }
})

This kind of code looks really tortured! When we write the code like this, we fall into a state of poor maintainability. The code experience is very bad, and I feel confused after looking at it for a while. In order to solve this problem, we introduced With our Promise, use Promise to solve the callback hell problem!

Promise


##Promise is asynchronous programming A solution that is more reasonable and powerful than the traditional solution - callback functions and events. It is a class provided by ECMAScript 6, which aims to write complex functions more elegantly. The Asynchronous tasks.
The Promise object has the following two characteristics:

    The state of the object is not affected by the outside world. The Promise object represents an asynchronous operation and has three states:
  • pending

    (in progress), fulfilled (successful) and rejected (failed). Only the result of the asynchronous operation can determine the current state, and no other operation can change this state. This is also the origin of the name Promise. Its English meaning is "promise", which means that it cannot be changed by other means.

  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

两个特点摘自于??阮一峰ES6文章

Promise语法格式

new Promise(function (resolve, reject) {
  // resolve 表示成功的回调
  // reject 表示失败的回调
}).then(function (res) {
  // 成功的函数
}).catch(function (err) {
  // 失败的函数
})

出现了new关键字,就明白了Promise对象其实就是一个构造函数,是用来生成Promise实例的。能看出来构造函数接收了一个函数作为参数,该函数就是Promise构造函数的回调函数,该函数中有两个参数resolvereject,这两个参数也分别是两个函数!

简单的去理解的话resolve函数的目的是将Promise对象状态变成成功状态,在异步操作成功时调用,将异步操作的结果,作为参数传递出去。reject函数的目的是将Promise对象的状态变成失败状态,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise实例生成以后,可以用then方法分别指定resolved状态rejected状态的回调函数。

代码示例:

        const promise = new Promise((resolve,reject)=>{
            //异步代码
            setTimeout(()=>{
                // resolve(['111','222','333'])
                reject('error')
            },2000)
        })
        promise.then((res)=>{
            //兑现承诺,这个函数被执行
            console.log('success',res);
        }).catch((err)=>{
            //拒绝承诺,这个函数就会被执行
            console.log('fail',err);
        })

代码分析:

上边说到Promise是一个构造函数,new之后等于说调用了构造函数,构造函数中传的参数是一个函数,这个函数内的两个参数分别又是两个函数(reslovereject),虽然感觉很绕,但是理清思路会很清晰的!


我们得到对象promise,promise对象中自带有两个方法thencatch,这两个方法中会分别再传入一个回调函数,这个回调函数的目的在于返回你所需要成功或失败的信息!那么怎么去调用这两个回调函数呢?
看下方图可以快速理解:

One article will help you master Promise easily
这两个函数分别做为参数(reslovereject)传到上方的函数中去了.随后在构造函数的回调函数中写入异步代码(例如:ajax定时器),这里使用了定时器作为例子,如果你想表达的是成功回调,你可以在内部调用函数reslove('一般情况下是后端返回的成功数据)。如果你想表达的是失败回调,你可以调用reject('一般情况下是后端返回的失败信息').

这些就是Promise执行的过程!虽然理解着很绕,但是多读几遍绝对有不一样的收获!

Promise链式

then方法返回的是一个新的Promise实例注意:不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法

实际案例:
我想要实现在一个数组中查看一个帖子,但是我最终的目的是得到这个帖子下面的所有评论,这该怎么实现呢?

实现思路
先从一个接口中获取这个帖子的信息,然后通过该帖子的帖子id从而获取到该帖子下的所有评论

代码如下:

pajax({
    url:"http://localhost:3000/news",
    data : {
        author : "james"
    }
}).then(res=>{
    return pajax({
        url : "http://localhost:3000/comments",
        data : {
            newsId : res[0].id
        }
    })
}).then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err);
})

代码分析:

这里使用了一个Promise已经封装过的ajax,我们从第一个接口中得到了帖子id,然后在then中的函数发送第二个请求(携带了第一个请求返回过来的参数),我们最后想要拿到第二个接口的结果,于是又有了一个then方法,但是在第一个then方法中要把一个新的Promise实例return出去,这样的话,第二个then才起作用!(这是因为then方法是Promise 实例所具有的方法,也就是说,then方法是定义在原型对象Promise.prototype上的)====>我们可以打印一下:console.log(Promise.prototype)

One article will help you master Promise easily
可以看的出来原型对象Promise.prototype中是有then方法的!

Promise.all()

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例

语法格式:

const p = Promise.all([p1, p2, p3]);

Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会调用Promise.reslove() [该方法可自行了解]自动将参数转为 Promise 实例,再进一步处理。

说那么多白话没用,我们可以根据一个案例,就可以明白Promise.all()的用途了。

实际案例:
如果你想实现一个效果:在一个页面中,等到页面中所有的请求返回数据后,再渲染页面,该怎么实现呢?(在实际开发中我们会看到loading加载页面,等数据返回完后,loading加载页面会消失,整个页面就展现出来了,增强用户的体验。)

实现思路:
通过Promise.all()方法,等多个接口全部接收到数据后,再统一进行处理,然后渲染页面

代码如下:

console.log("显示加载中")
const q1 = pajax({
    url:"http://localhost:3000/looplist"
})

const q2 = pajax({
    url:"http://localhost:3000/datalist"
})
Promise.all([q1,q2]).then(res=>{
    console.log(res)
    console.log("隐藏加载中...")
}).catch(err=>{
    console.log(err)
})

代码分析:

在上方代码中,全局打印显示加载中是代替loading的页面,表示该页面现在正是loading页面中,等到q1q2所请求接口都得到返回的信息后,在then方法中接收收据,并且可以进行渲染页面,同时隐藏了loading加载页面!

小结

不论是在前端的项目开发中还是在前端的面试过程中,Promise的地位就是举足轻重的,虽然解决异步编程的终极解决方案是async和await,但是它们也是基于Promise封装而来的,在以往文章中,我就说过,学习编程重要的是搞懂某个技术是怎么实现的,而不是做一个cv侠,多去思考,才能进步。继续加油吧,少年!

【相关推荐:javascript视频教程编程基础视频

The above is the detailed content of One article will help you master Promise easily. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:csdn.net. If there is any infringement, please contact admin@php.cn delete