Promise 是异步编程的一种解决方案。

Promise


/**
* 属性
*/
Promise.length
Promise.prototype /**
* 方法
*/
Promise.all(iterable) // 所有成功触发成功 任何失败触发失败
Promise.race(iterable) // 任意一个成功或失败后触发
Promise.reject(reason)
Promise.resolve(value) /**
* 原型
*/
Promise.prototype.constructor
//方法
Promise.prototype.catch(onRejected)
Promise.prototype.then(onFulfilled, onRejected)
Promise.prototype.finally(onFinally)

Promise 有三种状态

  • pending: 初始状态,既不是成功,也不是失败状态。
  • resolve: 意味着操作成功完成。(resoloved)
  • reject: 意味着操作失败。

pending

pending 是初始状态,执行 resolve/reject 会进入对应状态,如果不执行,责一直为 pending 状态

例如下面代码,promise 将一直在 pending 状态,不会执行 then/catch.

new Promise(function (resolve, reject) { })
.then(res => console.log(res))
.catch(err => console.log(err))

resolve

resolve 意味着操作成功完成, 如果有 .then,值会传入 .then 的第一个参数函数里。

new Promise(function (resolve, reject) {
resolve(1)
})
.then(res => console.log(res))

then 的第一个参数是成功的回调,第一个参数的返回值会影响接下来链的去向。第一个参数的返回值一般有三种情况

  • 无返回值:会去执行下一个 .then ,没有参数
  • 返回值非promise:调用下一个then的函数,参数为返回值
  • 返回值为promise:根据promise的执行结果,执行 下一个then/catch,如果一直是pending,则不执行下一个then/catch

例如想要在当前 then 终止,可以这样操作:

  .then((res) => new Promise(() => {}))

reject

reject 意味着操作失败。

使用 .catch 会捕获到错误信息。

与代码报错(如 undefined.a)不同的是, 代码报错如果不使用 catch 捕获,会向外传递,最终传递到根结点;而 reject 属于 promise 错误,即使不使用 catch 捕获也不会对全局有影响。

用 promise 实现 fetch

先来看几个问题:

  1. 如果请求 code 404, 会走 then 还是 catch? (答案:then)
  2. 控制台能看到一行 404 的错误, 为什么还是走 then 不是 catch 呢
  3. 如果请求跨域失败,走 then 还是 catch?(答案:catch)
  4. 同样是控制台看到错误,两者有什么区别呢?
  5. 跨域失败的报错, 和 then 中 undefined.a 报错,如果都不 catch,后者在 react 脚手架开发环境页面会蹦,两者有什么区别?

带着这几个问题,来看看 fetch。

fetch 返回值是 promise,所以有三种状态 pending、resolve、reject.

  • pending: 请求中
  • resolve: 请求成功(code 200/404/500 等, 非 200 控制台输出错误)
  • reject: 请求失败(跨域失败、连接超时、无网络等,控制台输出错误)

我们还发现,请求失败时,只能 catch 到最后一行错误, 如图

捕获后

为什么 404 在控制台看到错误,还走 then, resolve 如何实现

实现有几个难点,

  1. throw 后面代码不会执行;
  2. 先报错,后执行 then;
  3. catch 后错误不会打印在控制台;

试了下,Promise.reject('xxx') 这样的报错方式虽然是微观任务,但是总是在.then之后才在控制台输出,更像是宏观任务。所以也加个setTImeout宏观任务调至后面。

var fetch = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if ('请求成功 200') {
resolve('Response数据结构');
} else if ('请求成功 404,500等') {
Promise.reject('GET xxxxxxxx 404');
setTimeout(function () {
resolve('Response数据结构');
});
}
})
})
}

请求失败 例如跨域失败 reject 如何实现呢

同样加个 setTimeout

var fetch = function () {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if ('请求成功 200') {
resolve('Response数据结构');
} else if ('请求成功 404,500等') {
Promise.reject('GET xxxxxxxx 404');
setTimeout(function () {
resolve('Response数据结构');
});
} else if ('请求失败') {
Promise.reject('Access to fetch xxxxx with CORS disabled.');
Promise.reject('GET xxxxx net::ERR_FAILED');
setTimeout(function () {
reject('TypeError: Failed to fetch');
});
}
})
})
}

还是有些问题,我们实现的因为在promise 中,错误会有前缀 Uncaught (in promise)。浏览器客户端应该有更好的实现方式。

最后总结一下 fetch 的三种情况

  • pending: 请求中
  • resolve: 请求成功(code 200: 调用 resolve 返回数据; code: 404/500 等, 先抛错,再调用 resolve 返回数据。)
  • reject: 请求失败(跨域失败、连接超时、无网络等,先控制台抛错,再调用 reject)

抛错均不影响代码执行,与 undefined.a 不同。

whosmeya.com

谈谈 Promise 以及实现 Fetch 的思路的更多相关文章

  1. 基于Promise规范的fetch API的使用

    基于Promise规范的fetch API的使用 fetch的使用 作用:fetch 这个API,是专门用来发起Ajax请求的: fetch 是由原生 JS 提供的 API ,专门用来取代 XHR 这 ...

  2. 结合promise对原生fetch的两个then用法理解

    前言:该问题是由于看到fetch的then方法的使用,产生的疑问,在深入了解并记录对promise的个人理解 首先看一下fetch请求使用案例: 案例效果:点击页面按钮,请求当前目录下的arr.txt ...

  3. Promise简单实现(正常思路版)

    转自: http://www.jianshu.com/p/473cd754311f Promise 看了些promise的介绍,还是感觉不够深入,这个在解决异步问题上是一个很好的解决方案,所以详细看一 ...

  4. 第五节: 前后端交互之Promise用法和Fetch用法

    一. Promise相关 1.说明 主要解决异步深层嵌套的问题,promise 提供了简洁的API 使得异步操作更加容易 . 2.入门使用 我们使用new来构建一个Promise Promise的构造 ...

  5. 【原】谈谈promise

    最近在看<你不知道的javascript中卷>,发觉作者花了基本一半的篇幅去讲异步和promise,觉得有必要总结一下. 其实本文的目的是想手写一个Promise的,无奈总结着总结着发觉篇 ...

  6. 谈谈promise

    最近在看<你不知道的javascript中卷>,发觉作者花了基本一半的篇幅去讲异步和promise,觉得有必要总结一下. 其实本文的目的是想手写一个Promise的,无奈总结着总结着发觉篇 ...

  7. React Native 网络请求封装:使用Promise封装fetch请求

    最近公司使用React作为前端框架,使用了异步请求访问,这里做下总结: React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRe ...

  8. 【原】手写一个promise

    上一篇文章中,我们介绍了Promise的基本使用,在这篇文章中,我们试着自己来写一个Promise,主要是学习Promise的内部机制,学习它的编程思想. !!!备注:本文写的不好,仅供自己学习之用, ...

  9. fetch使用的常见问题及解决办法

    首先声明一下,本文不是要讲解fetch的具体用法,不清楚的可以参考MDN fetch教程. 引言 说道fetch就不得不提XMLHttpRequest了,XHR在发送web请求时需要开发者配置相关请求 ...

随机推荐

  1. C#线程 线程进阶

    第四部分:高级线程 非阻塞同步 前面我们说过,即使在分配或增加字段的简单情况下,也需要同步.尽管锁定始终可以满足此需求,但是竞争性锁定意味着线程必须阻塞,从而遭受上下文切换的开销和调度的延迟,这在高度 ...

  2. 最小生成树——Prim算法理解

    背景:本文是在小甲鱼数据结构教学视频中的代码的基础上,添加详细注释而完成的.该段代码并不完整,仅摘录了核心算法部分,结合自己的思考,谈谈理解. Prim算法理解: 如图(摘录自小甲鱼教学视频中的图片) ...

  3. Js 事件表格

  4. (Java实现) 洛谷 P1098 字符串的展开

    import java.util.ArrayList; import java.util.Scanner; public class zifuchuandezhankai { static Array ...

  5. Java实现 LeetCode 515 在每个树行中找最大值

    515. 在每个树行中找最大值 您需要在二叉树的每一行中找到最大的值. 示例: 输入: 1 / \ 3 2 / \ \ 5 3 9 输出: [1, 3, 9] /** * Definition for ...

  6. Java实现 LeetCode 11 盛最多水的容器

    11. 盛最多水的容器 给定 n 个非负整数 a1,a2,-,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) ...

  7. 第八届蓝桥杯JavaC组省赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1.外星日历 题目描述 某星系深处发现了文明遗迹. 他们的计数也是用十进制. 他们的文明也有日历.日历只有天数,没有年.月的概念. 有趣的 ...

  8. java实现第七届蓝桥杯分小组

    分小组 分小组 9名运动员参加比赛,需要分3组进行预赛. 有哪些分组的方案呢? 我们标记运动员为 A,B,C,... I 下面的程序列出了所有的分组方法. 该程序的正常输出为: ABC DEF GHI ...

  9. java实现第九届蓝桥杯三角形面积

    三角形面积 小明最近在玩一款游戏.对游戏中的防御力很感兴趣. 我们认为直接影响防御的参数为"防御性能",记作d,而面板上有两个防御值A和B,与d成对数关系,A=2^d,B=3^d( ...

  10. java代码(15) ---java8 Function 、Consumer 、Supplier

    Java8 Function.Consumer.Supplier 有关JDK8新特性之前还有三篇博客: 1,java代码(1)---Java8 Lambda 2,java代码(2)---Java8 S ...