JavaScript Promise 概述

本教程涵盖了 JavaScript Promise 的基础知识,展示了如何在 JavaScript 开发中利用它们。

承诺的概念对于 Web 开发来说并不新鲜。我们中的许多人已经以库的形式使用过 Promise,例如 Q、when.js、RSVP.js 等。甚至 jQuery 也有一个叫做Deferred object的东西,它类似于 Promise。但是现在我们在 JavaScript 中对 Promise 提供了原生支持,这真的很令人兴奋。

概述

Promise对象表示可能尚不可用但将在未来某个时间解决的值。它允许您以更同步的方式编写异步代码。例如,如果您使用 Promise API 对远程 Web 服务进行异步调用,您将创建一个Promise对象,该对象代表该 Web 服务将来返回的数据。需要注意的是,实际数据尚不可用。当请求完成并且从 Web 服务返回响应时,它将变为可用。同时,Promise对象充当实际数据的代理。此外,您可以将回调附加到Promise对象,一旦实际数据可用,就会调用该回调。

API

首先,让我们检查以下代码,它创建了一个新Promise对象:

const promise = new Promise((resolve, reject) => {
  //asynchronous code goes here
});

我们首先实例化一个新Promise对象并传递一个回调函数。回调有两个参数,resolvereject,它们都是函数。您所有的异步代码都在该回调中。如果一切顺利,则通过调用来履行承诺resolve()。如果发生错误,reject()则使用Error对象调用。这表明承诺被拒绝。

现在让我们构建一些简单的东西来展示如何使用 Promise。以下代码向 Web 服务发出异步请求,该请求返回 JSON 格式的随机笑话。让我们看看这里是如何使用 Promise 的:

const promise = new Promise((resolve, reject) => {
  const request = new XMLHttpRequest();

  request.open('GET', 'https://api.icndb.com/jokes/random');
  request.onload = () => {
    if (request.status === 200) {
      resolve(request.response); // we got data here, so resolve the Promise
    } else {
      reject(Error(request.statusText)); // status is not 200 OK, so reject
    }
  };

  request.onerror = () => {
    reject(Error('Error fetching data.')); // error occurred, reject the  Promise
  };

  request.send(); // send the request
});

console.log('Asynchronous request made.');

promise.then((data) => {
  console.log('Got data! Promise fulfilled.');
  document.body.textContent = JSON.parse(data).value.joke;
}, (error) => {
  console.log('Promise rejected.');
  console.log(error.message);
});

在前面的代码中,Promise构造函数回调包含用于从远程服务获取数据的异步代码。在这里,我们只是向https://api.icndb.com/jokes/random创建了一个 Ajax 请求,它返回一个随机笑话。当从远程服务器接收到 JSON 响应时,它会传递给resolve(). 如果出现任何错误,reject()则使用Error对象调用。

当我们实例化一个Promise对象时,我们会得到一个将来可用的数据的代理。在我们的例子中,我们期望在未来的某个时间点从远程服务返回一些数据。那么,我们如何知道数据何时可用?这是Promise.then()使用该功能的地方。这个函数有两个参数:一个成功回调和一个失败回调。这些回调在Promise解决(即完成或拒绝)时调用。如果 promise 被实现,成功回调将使用您传递给的实际数据触发resolve()。如果 promise 被拒绝,将调用失败回调。无论您传递给什么,reject()都将作为参数传递给此回调。

试试这个CodePen示例。要查看新的随机笑话,请点击嵌入右下角的RERUN按钮。此外,打开浏览器控制台,以便查看代码不同部分的执行顺序。

请注意,promise 可以具有三种状态:

  • 待处理(未完成或拒绝)
  • 完成
  • 拒绝

Promise.status属性是代码不可访问且私有的,提供有关这些状态的信息。一旦一个承诺被拒绝或履行,这个状态就会永久地与之关联。这意味着一个承诺只能成功或失败一次。如果promise 已经实现,然后你then()用两个回调将a 附加到它,那么成功回调将被正确调用。因此,在 Promise 的世界中,我们对知道 Promise 何时完成并不感兴趣。我们只关心承诺的最终结果。

链接承诺

有时需要将 Promise 链接在一起。例如,您可能需要执行多个异步操作。当一个操作为您提供数据时,您将开始对该数据块执行其他操作,依此类推。Promise 可以链接在一起,如以下示例所示:

function getPromise(url) {
  // return a Promise here
  // send an async request to the url as a part of promise
  // after getting the result, resolve the promise with it
}

const promise = getPromise('some url here');

promise.then((result) => {
  //we have our result here
  return getPromise(result); //return a promise here again
}).then((result) => {
  //handle the final result
});

棘手的部分是,当您在 内部返回一个简单值时,将使用该返回值调用then()下一个。then()但是如果你在里面返回一个promise then(),nextthen()会等待它并在promise 完成时被调用。

处理错误

您已经知道该then()函数将两个回调作为参数。如果 promise 被拒绝,将调用第二个。但是我们也有一个catch()函数,可以用来处理 promise 的拒绝。看看下面的代码:

promise.then((result) => {
  console.log('Got data!', result);
}).catch((error) => {
  console.log('Error occurred!', error);
});

这相当于:

promise.then((result) => {
  console.log('Got data!', result);
}).then(undefined, (error) => {A
  console.log('Error occurred!', erroAr);
});

请注意,如果 promise 被拒绝并且then()没有失败回调,则控件将前进到then()带有失败回调或 next 的下一个catch()。除了显式的 promise 拒绝之外,当构造函数回调catch()抛出任何异常时也会调用。Promise因此,您也可以catch()用于记录目的。请注意,我们可以使用它try...catch来处理错误,但对于 Promise,这不是必需的,因为任何异步或同步错误总是被catch().

结论

这只是对 JavaScript 的新 Promises API 的简要介绍。很明显,它让我们可以非常轻松地编写异步代码。我们可以照常进行,而不知道将来异步代码会返回什么值。API 的更多内容未在此处介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值