Rumah  >  Artikel  >  hujung hadapan web  >  JavaScript: Menjaga perkataan kami

JavaScript: Menjaga perkataan kami

王林
王林asal
2023-09-01 15:53:02773semak imbas

JavaScript: Menjaga perkataan kami

JavaScript, melalui popularitinya dan peningkatan terkini, semakin menjadi rakan baik pengaturcara web. Seperti semua kawan baik, JavaScript menepati janjinya.

Ini mungkin kedengaran agak pelik, tetapi ia benar. Kebanyakan penyemak imbas pada masa ini menyokong objek yang dipanggil Promise. Janji adalah seperti fungsi yang mewakili sekeping kod atau tugasan yang ingin anda laksanakan pada satu ketika pada masa hadapan.

Beginilah rupa komitmen.

var myPromise = new Promise(function (resolve, reject) {
    // Task to carry out goes here.
});

Anda boleh lihat di sini bahawa apabila kami membuat Promise, kami memberikannya parameter, iaitu fungsi yang mengandungi kod yang ingin kami laksanakan pada satu ketika pada masa hadapan. Anda juga mungkin melihat dua parameter yang dihantar kepada Promise dalam fungsi: resolve dan reject. Ini juga fungsi, dan cara kami memberitahu Janji sama ada ia dipenuhi. Begini cara anda menggunakannya: resolvereject。这些也是函数,是我们告诉 Promise 是否完成了承诺的方式。这是您使用它们的方式:

var myPromise = new Promise(function (resolve, reject) {
    if (true) {
        resolve('Hello Tuts+ fans!');
    } else {
        reject('Aww, didn\'t work.');
    }
});

这个承诺显然总是会得到解决,因为 if 语句将始终为真。这只是出于学习目的 - 我们稍后会做一些更实际的事情 - 但想象一下用一段您不能 100% 确定是否有效的代码片段替换 true

现在我们已经创建了一个 Promise,我们该如何使用它呢?好吧,我们需要告诉它 resolvereject 函数是什么。我们通过使用 Promise 的 then 方法来做到这一点。

myPromise.then(function (result) {
    // Resolve callback.
    console.log(result); 
}, function (result) {
    // Reject callback.
    console.error(result);
});

因为我们的 if 语句总是通过其 true 检查,所以上面的代码将始终记录“Hello Tuts+球迷!”到控制台。它也会立即执行。这是因为 Promise 构造函数内的代码是同步的,这意味着它不会等待任何操作的执行。它拥有继续进行所需的所有信息,并会尽快进行。

然而,Promise 真正发挥作用的地方是异步任务,即您不知道 Promise 何时具体实现的任务。异步任务的一个现实示例是通过 AJAX 获取资源,例如 JSON 文件。我们不知道服务器需要多长时间才能响应,甚至可能会失败。让我们在 Promise 代码中添加一些 AJAX。

var myPromise = new Promise(function (resolve, reject) {
    // Standard AJAX request setup and load.
    var request = new XMLHttpRequest();
    
    // Request a user's comment from our fake blog.
    request.open('GET', 'http://jsonplaceholder.typicode.com/posts/1');

    // Set function to call when resource is loaded.
    request.onload = function () {
        if (request.status === 200) {
            resolve(request.response);
        } else {
            reject('Page loaded, but status not OK.');
        }
    };

    // Set function to call when loading fails.
    request.onerror = function () {
        reject('Aww, didn\'t work at all.');
    }

    request.send();
});

这里的代码只是用于执行 AJAX 请求的标准 JavaScript。我们请求一个资源,在本例中是指定 URL 处的 JSON 文件,并等待它响应。我们永远不会知道确切的时间。我们显然不想停止执行脚本来等待它,那么我们该怎么办呢?

幸运的是,我们已将此代码放入 Promise 中。把它放在这里,我们基本上是在说,“嘿,一段代码,我现在得走了,但我稍后会给你打电话,告诉你何时执行。保证你会这么做并告诉我你什么时候完成?”代码会说:“是的,当然。我保证。”

上面代码中需要注意的重要一点是 resolvereject 函数的调用。请记住,这些是我们告诉我们的承诺我们的代码是否成功执行的方式。否则,我们永远不会知道。

使用基本示例中的相同代码,我们可以看到 Promise 中的 AJAX 请求现在将如何工作。

// Tell our promise to execute its code
// and tell us when it's done.
myPromise.then(function (result) {
    // Prints received JSON to the console.
    console.log(result);
}, function (result) {
    // Prints "Aww didn't work" or
    // "Page loaded, but status not OK."
    console.error(result); 
});

我知道我们可以信任你,myPromise

链接承诺

现在,您可能会认为 Promise 只是具有更好语法的奇特回调函数。这在某种程度上是正确的,但为了继续我们的 AJAX 示例,假设您需要再发出一些请求,每个请求都基于上一个请求的结果。或者如果您需要先处理 JSON 怎么办?

使用回调执行此操作将导致函数的大量嵌套,每个函数都变得越来越难以跟踪。幸运的是,在 Promise 的世界中,我们可以像这样将这些函数链接在一起。下面是一个示例,一旦我们收到用户在我们的假博客上发表的评论的 JSON,我们就需要确保它全部是小写,然后再对其进行其他操作。

myPromise
    .then(function (result) {
        // Once we receive JSON,
        // turn it into a JSON object and return.
        return JSON.parse(result);
    })
    .then(function (parsedJSON) {
        // Once json has been parsed,
        // get the email address and make it lowercase.
        return parsedJSON.email.toLowerCase();
    })
    .then(function (emailAddress) {
        // Once text has been made lowercase,
        // print it to the console.
        console.log(emailAddress);
    }, function (err) {
        // Something in the above chain went wrong?
        // Print reject output.
        console.error(err);
    });

您可以在此处看到,虽然我们的初始调用是异步的,但也可以链接同步调用。 resolve 函数中的代码在 then 每个返回时都会被调用。您还会注意到,这里只为整个链指定了一个误差函数。通过将其作为最后一个 then 中的 reject 函数放在链的末尾,链中调用 reject

var sendEmail = function (emailAddress) {
    return new Promise(function (resolve, reject) {
        // Pretend to send an email
        // or do something else asynchronous
        setTimeout(function () {
            resolve('Email sent to ' + emailAddress);
        }, 3000);
    });
};

Janji ini jelas akan sentiasa diselesaikan kerana kenyataan if akan sentiasa benar. Ini hanya untuk tujuan pembelajaran - kami akan melakukan sesuatu yang lebih praktikal kemudian - tetapi bayangkan menggantikan true dengan coretan kod yang anda tidak pasti 100% sah. 🎜Sekarang kita telah mencipta Janji, bagaimana kita menggunakannya? Nah, kita perlu memberitahunya apakah fungsi resolve dan reject. Kami melakukan ini dengan menggunakan kaedah then Promise. 🎜
myPromise
    .then(function (result) {
        return JSON.parse(result);
    })
    .then(function (parsedJSON) {
        return parsedJSON.email.toLowerCase();
    })
    .then(function (emailAddress) {
        return sendEmail(emailAddress)
    })
    .then(function (result) {
        // Outputs "Email sent to stuart@fakemail.biz"
        console.log(result);
    }, function (err) {
        console.error(err);
    });
🎜Oleh kerana pernyataan if kami sentiasa melepasi semakan true, kod di atas akan sentiasa log "Hello Tuts+fans!" Ia juga dilaksanakan serta-merta. Ini kerana kod di dalam pembina Promise adalah segerak, bermakna ia tidak menunggu sebarang operasi dilakukan. Ia mempunyai semua maklumat yang diperlukan untuk meneruskan, dan akan melakukannya secepat mungkin. 🎜 🎜Namun, di mana Janji benar-benar bersinar adalah dalam tugas tak segerak, tugas yang anda tidak tahu dengan tepat bila Janji akan ditunaikan. Contoh dunia nyata bagi tugas tak segerak ialah mengambil sumber, seperti fail JSON, melalui AJAX. Kami tidak tahu berapa lama masa yang diambil untuk pelayan bertindak balas, atau jika ia mungkin gagal. Mari tambahkan beberapa AJAX pada kod Promise kami. 🎜 rrreee 🎜Kod di sini hanyalah JavaScript standard untuk melaksanakan permintaan AJAX. Kami meminta sumber, dalam kes ini, fail JSON pada URL yang ditentukan dan tunggu sehingga ia bertindak balas. Kita tidak akan pernah tahu bila. Kami jelas tidak mahu berhenti melaksanakan skrip untuk menunggunya, jadi apa yang kami lakukan? 🎜 🎜Nasib baik, kami telah meletakkan kod ini ke dalam Janji. Dengan meletakkannya di sini, kami pada asasnya berkata, "Hei, sekeping kod, saya perlu pergi sekarang, tetapi saya akan menghubungi anda kemudian dan memberitahu anda bila untuk melaksanakannya. Berjanji anda akan melakukannya dan memberitahu saya anda Bilakah ia akan dilakukan?" Kod akan berkata: "Ya, sudah tentu." 🎜 🎜Perkara penting untuk diperhatikan dalam kod di atas ialah panggilan fungsi resolve dan reject. Ingat, ini adalah cara kami memberitahu janji kami sama ada kod kami berjaya dilaksanakan. Jika tidak, kita tidak akan tahu. 🎜 🎜Menggunakan kod yang sama daripada contoh asas, kita dapat melihat cara permintaan AJAX dalam Promise kini akan berfungsi. 🎜 rrreee 🎜Saya tahu kami boleh mempercayai anda, MyPromise. 🎜

Paut janji

🎜Kini, anda mungkin berfikir bahawa Promises hanyalah fungsi panggil balik yang mewah dengan sintaks yang lebih baik. Ini benar sedikit sebanyak, tetapi untuk meneruskan contoh AJAX kami, katakan anda perlu membuat beberapa permintaan lagi, setiap satu berdasarkan hasil permintaan sebelumnya. Atau bagaimana jika anda perlu memproses JSON terlebih dahulu? 🎜 🎜Melakukan ini menggunakan panggil balik akan mengakibatkan banyak fungsi bersarang, setiap satu menjadi semakin sukar untuk dijejaki. Nasib baik, dalam dunia Janji, kita boleh rantai fungsi ini bersama-sama seperti ini. Berikut ialah contoh, sebaik sahaja kami menerima JSON ulasan pengguna pada blog palsu kami, kami perlu memastikan semuanya menggunakan huruf kecil sebelum melakukan perkara lain dengannya. 🎜 rrreee 🎜Anda boleh lihat di sini bahawa walaupun panggilan awal kami adalah tak segerak, anda juga boleh membuat rangkaian panggilan segerak. Kod dalam fungsi resolve dipanggil setiap kali then kembali. Anda juga akan melihat bahawa hanya satu fungsi ralat ditentukan di sini untuk keseluruhan rantai. Dengan meletakkannya di penghujung rantai sebagai fungsi reject terakhir dalam rantai, rangkaian yang memanggil reject akan panggil fungsi ini. 🎜

现在我们对承诺更有信心了,让我们结合上面的承诺创建另一个承诺。我们将创建一个采用新的小写电子邮件地址的电子邮件地址,并(假装)向该地址发送电子邮件。这只是一个说明异步内容的示例 - 它可以是任何内容,例如联系服务器以查看电子邮件是否在白名单上或者用户是否已登录。我们需要将电子邮件地址提供给新的 Promise,但承诺不接受争论。解决这个问题的方法是将 Promise 包装在一个可以执行此操作的函数中,如下所示:

var sendEmail = function (emailAddress) {
    return new Promise(function (resolve, reject) {
        // Pretend to send an email
        // or do something else asynchronous
        setTimeout(function () {
            resolve('Email sent to ' + emailAddress);
        }, 3000);
    });
};

我们在此处使用 setTimeout 调用来简单地伪造一个需要几秒钟才能异步运行的任务。

那么我们如何使用新的承诺创建函数呢?好吧,由于在 then 中使用的每个 resolve 函数都应该返回一个函数,那么我们可以以与同步任务类似的方式使用它。

myPromise
    .then(function (result) {
        return JSON.parse(result);
    })
    .then(function (parsedJSON) {
        return parsedJSON.email.toLowerCase();
    })
    .then(function (emailAddress) {
        return sendEmail(emailAddress)
    })
    .then(function (result) {
        // Outputs "Email sent to stuart@fakemail.biz"
        console.log(result);
    }, function (err) {
        console.error(err);
    });

让我们回顾一下这个流程,总结一下发生了什么。我们最初的 Promise myPromise 请求一段 JSON。当收到该 JSON 时(我们不知道何时),我们将 JSON 转换为 JavaScript 对象并返回该值。

完成后,我们从 JSON 中取出电子邮件地址并将其变为小写。然后我们向该地址发送一封电子邮件,同样我们不知道它何时完成,但当它完成时,我们将向控制台输出一条成功消息。看不到沉重的嵌套。

结论

我希望这是对 Promise 的有用介绍,并为您提供了在 JavaScript 项目中开始使用它们的充分理由。如果您想更详细地了解 Promise,请查看 Jake Archibald 关于这个主题的优秀 HTML5 Rocks 文章。

学习 JavaScript:完整指南

我们构建了一个完整的指南来帮助您学习 JavaScript,无论您是刚刚开始作为 Web 开发人员还是想探索更高级的主题。

Atas ialah kandungan terperinci JavaScript: Menjaga perkataan kami. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn