Rumah  >  Artikel  >  hujung hadapan web  >  Satu artikel akan membantu anda menguasai Promise dengan mudah

Satu artikel akan membantu anda menguasai Promise dengan mudah

青灯夜游
青灯夜游ke hadapan
2023-02-10 19:49:162249semak imbas

Satu artikel akan membantu anda menguasai Promise dengan mudah

Dalam pembelajaran js bahagian hadapan, perkara yang paling tidak selesa untuk semua orang ialah masalah tak segerak Apabila menyelesaikan masalah seperti 异步、回调地狱, anda mesti belajar janji , janji hanyalah Mimpi ngeri, artikel ini adalah titik masuk dari perspektif yang mudah difahami untuk membantu anda menguasai janji dengan mudah

Pengaturcaraan tak segerak


Jika anda ingin belajar janji, anda mesti faham apa itu pengaturcaraan tak segerak! Seperti yang kita sedia maklum, bahasa js ialah mekanisme 单线程. Apa yang dipanggil utas tunggal bermaksud melaksanakan mengikut tertib, melaksanakan satu tugas sebelum melaksanakan tugas seterusnya. Walau bagaimanapun, ia tidak menjejaskan kewujudan dua operasi 同步 dan 异步 Kedua-dua operasi ini sebenarnya melakukan perkara pada saluran paip (single thread), tetapi susunan pelaksanaan kedua-dua operasi ini pada satu thread adalah berbeza! Apabila js mencetuskan tugas tak segerak, tugas tak segerak akan diserahkan kepada penyemak imbas untuk diproses Apabila pelaksanaan terhasil, fungsi panggil balik tugas tak segerak akan dimasukkan ke penghujung baris gilir untuk diproses!

Mari kita terangkan tak segerak kami dengan cara yang mudah: 异步就是从主线程发射一个子线程来完成任务, setiap tugasan mempunyai satu atau lebih fungsi panggil balik (panggilan balik), 前一个任务结束后,不是执行后一个任务,而是执行回调函数, 后一个任务则是不等前一个任务结束就执行, jadi susunan pelaksanaan program It tidak konsisten dengan susunan tugasan dan tak segerak.

Satu artikel akan membantu anda menguasai Promise dengan mudah

Gambar ini diambil daripada bahagian Tutorial Rookie异步编程, bantu Semua orang lebih memahami apa itu tak segerak! Takrif fungsi panggil balik adalah sangat mudah: fungsi dianggap sebagai

Dilalui ke fungsi lain (
), dan fungsi ini dipanggil dalam fungsi luaran untuk menyelesaikan tugas tertentu. Ia dipanggil dua cara untuk menulis fungsi panggil balik (

): :


实参 dalam kod ini ialah penggunaan Untuk proses yang panjang, parameter pertamanya ialah 外部函数 dan parameter kedua ialah 回调函数 Selepas fungsi ini dilaksanakan, utas anak akan dijana selama 1 saat dan kemudian melaksanakan fungsi panggil balik

, output

实现效果相同setTimeout dalam teks akan menunggu selama 1 saat dalam thread anak, tetapi operasi thread utama tidak akan terjejas! Contohnya, kod berikut:

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

akan mencetak setTimeout(回调函数) dahulu, dan kemudian mengeluarkan 毫秒数("text")hello james dalam teks satu kedua kemudiannya. anda mesti memahaminya. Apakah

dan mengapa neraka panggilan balik berlaku?

Mari kita lihat konsepnya dahulu:

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

: 123456 Contohnya, kami menghantar tiga permintaan ajax: 主线程hello davis子线程

Yang pertama dihantar seperti biasa

Yang kedua satu Permintaan memerlukan nilai tertentu daripada hasil permintaan pertama sebagai parameter Permintaan ketiga memerlukan nilai tertentu daripada hasil permintaan kedua sebagai parameter


Anda akan melihat kod berikut

:回调地狱
当一个回调函数嵌套一个回调函数的时候就会出现一个嵌套结构当嵌套的多了就会出现回调地狱的情况
Kod jenis ini kelihatan sangat terseksa! Apabila kami menulis kod seperti ini, kami jatuh ke dalam keadaan Pengalaman kod itu sangat teruk, dan saya keliru selepas membacanya untuk beberapa ketika, kami memperkenalkan kami. gunakan Janji untuk menyelesaikan masalah neraka panggilan balik!

    Janji

adalah lebih baik daripada penyelesaian tradisional - Fungsi panggilan balik dan Acara - Lebih munasabah dan berkuasa, ia adalah yang bertujuan untuk menulis kompleks

dengan lebih elegan.
$.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) 
          }
        })
      }
    })
  }
})

Objek janji mempunyai dua ciri berikut: 可维护性差Promise

Keadaan objek tidak dipengaruhi oleh dunia luar. Objek Promise mewakili operasi tak segerak dan mempunyai tiga keadaan:

(sedang berjalan), (berjaya) dan (gagal).

. Ini juga asal usul nama Promise Maksud bahasa Inggerisnya ialah

, yang bermaksud ia tidak boleh diubah dengan cara lain.

  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。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,这两个方法中会分别再传入一个回调函数,这个回调函数的目的在于返回你所需要成功或失败的信息!那么怎么去调用这两个回调函数呢?
    看下方图可以快速理解:

    Satu artikel akan membantu anda menguasai Promise dengan mudah
    这两个函数分别做为参数(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)

    Satu artikel akan membantu anda menguasai Promise dengan mudah
    可以看的出来原型对象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视频教程编程基础视频

    Atas ialah kandungan terperinci Satu artikel akan membantu anda menguasai Promise dengan mudah. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    Kenyataan:
    Artikel ini dikembalikan pada:csdn.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam