1. 概述

在上一篇文章《JavaScript异步编程1——Promise的初步使用》,简单介绍了一下Promise的初步使用。复习一下,Promise异步编程可以用如下的范式来编写:

  1. 定义一个函数(function A),这个函数返回一个Promise对象。
  2. Promise对象的参数也是一个function B,内部进行了一个异步操作(通常是JavaScript提供的API)。
  3. function B对象的参数是两个回调函数resolve和reject。如果函数内部进行的异步操作成功,回调resolve;否则回调reject。
  4. 调用function A,返回一个Promise对象,这样异步操作就启动了。
  5. 调用Promise对象的then方法,参数是resolve和reject的真正响应函数。当异步操作完成了,就会执行相应分支的响应函数。

采用以上范式,可以通过Promise来进行Ajax操作,也就是XMLHttpRequest,毕竟这个操作在Web应用中实在太常见了。

2. 详论

首先仍然是准备一个HTML页面:

<!DOCTYPE html>
<html> <head>
<meta charset="utf-8">
<script src="./3rdParty/jquery-3.5.1.js"></script>
<title>样例</title>
</head> <body>
<div id = "container"> </div>
<script src="./PromiseTest.js"></script>
</body> </html>

如果不使用Promise,那么相应的JavaScript代码为:

$(function () {

    var url = "./1.json";

    var req = new XMLHttpRequest();
req.open('GET', url); req.onload = function () {
if (req.status == 200) {
console.log(req.response);
} else {
throw new Error(req.statusText);
}
}; req.onerror = function () {
throw new Error("Network Error");
}; req.send();
});

可以看到这里仍然是通过事件机制来实现异步行为。接下来采用前面提到的编程范式将其改造成Promise机制:

function get(url) {
return new Promise(function (resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url); req.onload = function () {
//即使是404也会进入这个相应函数,所以需要检测状态
if (req.status == 200) {
//完成许诺,返回响应文本
resolve(req.response);
} else {
//完成未完成,返回错误
reject(Error(req.statusText));
}
}; // 发生错误时的相应函数
req.onerror = function () {
reject(Error("Network Error"));
}; // 发送请求
req.send();
});
} var addressUri = "./1.json";
get(addressUri).then(function (response) {
console.log("Success!", response);
}, function (error) {
console.error("Failed!", error);
});

改造成Promise的过程与上一章并没有什么不同,只不过函数内部调用XMLHttpRequest的流程更加复杂些。这两个例子都是将事件改造成Promise,那不是意味着对于异步编程而言,Promise要优于事件呢?

不能完全这么肯定,但是可以确定的是事件并不总是异步编程的最优实践。一个很显然的问题就是:事件很适合处理在同一对象上多次发生的事情,但是事件侦听器的响应函数可能并不是我们想要的——更多情况下,我们只想要直到两个状态,当异步操作完成的时候该做什么,当异步操作失败的时候又该做什么,而这正是Promise擅长处理的。

例如这里的XMLHttpRequest操作,事件响应函数onload中的所有行为,并不都是异步请求成功时需要完成的,只有检测访问请求状态为200时候,才需要进行请求成功时的回调函数。使用Promise,可以更准确的进行异步行为。

3. 参考

  1. Ajax原理-原生js的XMLHttpRequest对象意义
  2. Javascript异步编程的4种方法

JavaScript异步编程2——结合XMLHttpRequest使用Promise的更多相关文章

  1. JavaScript 异步编程(二):Promise

    PromiseState Promise 有一个 [[PromiseState]] 属性,表示当前的状态,状态有 pending 和 fulfill 以及 reject. 从第一个 Promise 开 ...

  2. javascript异步编程,promise概念

    javascript 异步编程 概述 采用单线程模式工作的原因: 避免多线dom操作同步问题,javascript的执行环境中负责执行代码的线程只有一个 内容概要 同步模式和异步模式 事件循环和消息队 ...

  3. JavaScript异步编程原理

    众所周知,JavaScript 的执行环境是单线程的,所谓的单线程就是一次只能完成一个任务,其任务的调度方式就是排队,这就和火车站洗手间门口的等待一样,前面的那个人没有搞定,你就只能站在后面排队等着. ...

  4. JavaScript异步编程的主要解决方案—对不起,我和你不在同一个频率上

    众所周知(这也忒夸张了吧?),Javascript通过事件驱动机制,在单线程模型下,以异步的形式来实现非阻塞的IO操作.这种模式使得JavaScript在处理事务时非常高效,但这带来了很多问题,比如异 ...

  5. javascript异步编程的前世今生,从onclick到await/async

    javascript与异步编程 为了避免资源管理等复杂性的问题, javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是为 ...

  6. JavaScript异步编程(2)- 先驱者:jsDeferred

    JavaScript当前有众多实现异步编程的方式,最为耀眼的就是ECMAScript 6规范中的Promise对象,它来自于CommonJS小组的努力:Promise/A+规范. 研究javascri ...

  7. Promises与Javascript异步编程

    Promises与Javascript异步编程 转载:http://www.zawaliang.com/2013/08/399.html 在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这 ...

  8. 5分种让你了解javascript异步编程的前世今生,从onclick到await/async

      javascript与异步编程 为了避免资源管理等复杂性的问题,javascript被设计为单线程的语言,即使有了html5 worker,也不能直接访问dom. javascript 设计之初是 ...

  9. 转: Promises与Javascript异步编程

    在如今都追求用户体验的时代,Ajax应用真的是无所不在.加上这些年浏览器技术.HTML5以及CSS3等的发展,越来越多的富Web应用出现:在给与我们良好体验的同时,Web开发人员在背后需要处理越来越多 ...

  10. JavaScript异步编程

    前言 如果你有志于成为一个优秀的前端工程师,或是想要深入学习JavaScript,异步编程是必不可少的一个知识点,这也是区分初级,中级或高级前端的依据之一.如果你对异步编程没有太清晰的概念,那么我建议 ...

随机推荐

  1. Java核心知识体系5:反射机制详解

    Java核心知识体系1:泛型机制详解 Java核心知识体系2:注解机制详解 Java核心知识体系3:异常机制详解 Java核心知识体系4:AOP原理和切面应用 1 介绍 无论是那种语言体系,反射都是必 ...

  2. Python:基础&爬虫

    Python:基础&爬虫 Python爬虫学习(网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另 ...

  3. Kubernetes:kube-apiserver 之启动流程(二)

    接着 Kubernetes:kube-apiserver 之启动流程(一) 加以介绍. 1.2.2 创建 APIExtensions Server 创建完通用 APIServer 后继续创建 APIE ...

  4. 23. 从零用Rust编写正反向代理,流控小姐姐的温柔一刀!

    wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现 ...

  5. clickHouse-golang

    目录 clickHouse优势与劣势 golang操作clickHouse clickHouse优势与劣势 ClickHouse和传统的MySQL在设计和使用场景上有一些显著的区别,因此它们各自具有不 ...

  6. LOG日志系统

    # coding=utf-8 import datetime import logging import os import sys from logging.handlers import Time ...

  7. 【解决方案】MySQL5.7 百万数据迁移到 ElasticSearch7.x 的思考

    目录 前言 一.一次性全量 二.定时任务增量 三.强一致性问题 四.canal 框架 4.1基本原理 4.2安装使用(重点) 版本说明 4.3引入依赖(测试) 4.4代码示例(测试) 五.文章小结 前 ...

  8. [USACO2007NOVG] Telephone Wire G

    题目描述 Farmer John's cows are getting restless about their poor telephone service; they want FJ to rep ...

  9. storeToRefs()的作用和使用

    store 是一个用 reactive 包装的对象,这意味着不需要在 getters 后面写 .value,就像 setup 中的 props 一样,如果你写了,我们也不能解构它: <scrip ...

  10. 接手了个项目,被if..else搞懵逼了

    背景 领导:"这个项目,今后就给你维护了啊,仔细点." 小猫:"好,没问题". 可当满怀信心的小猫打开项目工程包翻看一些代码之后,瞬间懵逼没了信心. 是这样的 ...