认识JavaScript Promise
参考:
EC前端 - Promise - http://www.ecmaer.com/javascript/nativeObj/promise.html
关于Promise:
- 什么是 Promise?
Promise 是异步编程的一种解决方案,比传统的异步解决方案【回调函数】和【事件】更合理、更强大。现已被 ES6 纳入进规范中。
Promise是一个方案,用来解决多层回调嵌套的解决方案
Promise 的常规写法:
new Promise(请求1)
.then(请求2(请求结果1))
.then(请求3(请求结果2))
.then(请求4(请求结果3))
.then(请求5(请求结果4))
.catch(处理异常(异常信息))
Promise 的写法更为直观,并且能够在外层捕获异步函数的异常信息
- Promise 解决的痛点是什么?
回调地狱
需要根据前一个网络请求的结果,再去执行下一个网络请求,代码大概如下:
请求1(function(请求结果1){
请求2(function(请求结果2){
请求3(function(请求结果3){
请求4(function(请求结果4){
请求5(function(请求结果5){
请求6(function(请求结果3){
...
})
})
})
})
})
})
回调地狱带来的负面作用有以下几点:
1、代码臃肿;
2、可读性差;
3、耦合度过高,可维护性差;
4、代码复用性差;
5、容易滋生 bug;
6、只能在回调里处理异常;
为了能使用一种更加友好的代码组织方式,解决异步嵌套的问题:
let 请求结果1 = 请求1();
let 请求结果2 = 请求2(请求结果1);
let 请求结果3 = 请求3(请求结果2);
let 请求结果4 = 请求2(请求结果3);
let 请求结果5 = 请求3(请求结果4);
Promise 的业界实现都有哪些?
业界著名的 Q 和 bluebird,bluebird 甚至号称运行最快的类库Promise 解决的痛点还有其他方法可以解决吗?如果有,请列举。
为了解决“回调地狱”,我们可以使用文中所述的这五种常用方法:
1、function拆解
回调嵌套所带来的一个重要问题就是代码不易阅读与维护。因为普遍来说,过多的缩进(嵌套)会极大的影响代码的可读性。基于这一点,
可以进行一个最简单的优化——将各步拆解为单个的function
2、事件发布/订阅模式
我们可以监听某一事件,当事件发生时,进行相应回调操作;另一方面,当某些操作完成后,通过发布事件触发回调。这样就可以将原本捆绑在一起的代码解耦。
3、Promise
4、Generator
generator是es6中的一个新的语法。在function关键字后添加*即可将函数变为generator
const gen = function* () {
yield 1;
yield 2;
return 3;
}
let g = gen();
g.next(); // { value: 1, done: false }
g.next(); // { value: 2, done: false }
g.next(); // { value: 3, done: true }
g.next(); // { value: undefined, done: true }
generator函数有一个最大的特点,可以在内部执行的过程中交出程序的控制权,yield相当于起到了一个暂停的作用;而当一定情况下,外部又将控制权再移交回来
5、async / await
es7中的async/await
在async函数中可以使用await语句。await后一般是一个Promise对象
async function foo () {
console.log('开始');
let res = await post(data);
console.log(`post已完成,结果为:${res}`);
};
4、Promise 如何使用?
// 声明函数
function run(callback) {
let parmas = 0;
if (callback) callback(parmas);
};
function fnStep1(callback) {
let parmas = 123;
if (callback) callback(parmas);
};
function fnStep2(callback) {
let parmas = 456;
if (callback) callback(parmas);
};
function fnStep3(callback) {
let parmas = 789;
if (callback) callback(parmas);
};
// fnStep4 ...
// 传统使用回调的写法
run(function (parmas) {
// parmas = 0
console.log(parmas);
fnStep1(function (parmas1) {
// parmas = 123
console.log(parmas1);
fnStep2(function (parmas2) {
// parmas = 456
console.log(parmas2);
fnStep3(function (parmas3) {
// ...
// 一直嵌套
});
});
});
});
let p = new Promise((resolve, reject) => {
const parmas = 0;
resolve(parmas); // fulfilled
// reject("failure reason"); // rejected
})
p.then(
(parmas) => {
// parmas,resolve返回的值
console.log(parmas); //0
return 123; //返回值给下一个then
}
)
.then(
(parmas) => {
// parmas,上一个then返回的值
console.log(parmas); //123
return 456; //返回值给下一个then
}
)
.then(
(parmas) => {
// parmas,上一个then返回的值
console.log(parmas); //456
return 789; //返回值给下一个then
})
- Promise 常用的方法,方法的作用?
1、race
多个promise 任务同时执行,只返回最先执行完的 Promise 任务的结果;
2、all
多个promise 任务同时执行,返回所有promise 任务的执行结果;
6、Promise 在事件循环中的执行过程是怎样的?
构造函数传入的参数是什么类型?
它接收的参数是一个匿名函数,任何情况下,它里面的js最先执行。
这个匿名函数也有二个参数:
1、resolve,完成,操作成功时调用。
2、reject,失败,操作失败时调用。传入的该函数是会立刻执行的吗?
会在本次new 操作立刻执行。
第一次resolve就确定了自己是成功还是失败。第二次没用了。添加reject也改变不了若调用了两次resolve方法会怎么样?
只执行第一次resolve发生异常会怎么样?
promise的原理?jquery的ajax返回的是promise对象吗?(百度面试)
promise 只有2个状态,成功和失败,怎么让一个函数无论成功和失败都能被调用?
Promise.all() 是干什么用的,怎么用?初始化Promise对象的方法
new Promise(fn)
Promise.resolve(fn)
/*
*end
*nextTick
*then
*setImmediate
*
*process.nextTick 和 promise.then 都属于 microtask
* 而 setImmediate 属于 macrotask
* 在事件循环的 check 阶段执行
* 事件循环的每个阶段(macrotask)之间都会执行 microtask,事件循环的开始会先执行一次 microtask
*
*/
process.nextTick(()=>{
console.log('nextTick');
});
Promise.resolve().then(()=>{
console.log('then');
});
setImmediate(()=>{
console.log('setImmediate');
});
console.log('end');
Promise扩展之事件循环机制:
macrotasks:
- setTimeout
- setInterval
- setImmediate
- requestAnimationFrame
- I/O
- UI rendering
microtasks:
- process.nextTick
- Promises
- Object.observe
- MutationObserver
任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。
同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
执行优先级的问题 microtasks > macrotasks
在每一次事件循环中,macrotask 只会提取一个执行,而 microtask 会一直提取,直到 microtasks 队列清空。
而事件循环每次只会入栈一个 macrotask ,主线程执行完该任务后又会先检查 microtasks 队列并完成里面的所有任务后再执行 macrotask
setImmediate(function(){
console.log(1);
},0);
setTimeout(function(){
console.log(2);
},0);
new Promise(function(resolve){
console.log(3);
resolve();
console.log(4);
}).then(function(){
console.log(5);
});
console.log(6);
process.nextTick(function(){
console.log(7);
});
console.log(8);
//3 4 6 8 7 5 2 1
认识JavaScript Promise的更多相关文章
- [Javascript] Promise
Promise 代表着一个异步操作,这个异步操作现在尚未完成,但在将来某刻会被完成. Promise 有三种状态 pending : 初始的状态,尚未知道结果 fulfilled : 代表操作成功 r ...
- Javascript Promise 学习笔记
1. 定义:Promise是抽象异步处理对象以及对其进行各种操作的组件,它把异步处理对象和异步处理规则采用统一的接口进行规范化. 2. ES6 Promises 标准中定义的API: ...
- 【译】JavaScript Promise API
原文地址:JavaScript Promise API 在 JavaScript 中,同步的代码更容易书写和 debug,但是有时候出于性能考虑,我们会写一些异步的代码(代替同步代码).思考这样一个场 ...
- JavaScript Promise:去而复返
原文:http://www.html5rocks.com/en/tutorials/es6/promises/ 作者:Jake Archibald 翻译:Amio 女士们先生们,请准备好迎接 Web ...
- javaScript Promise 入门
Promise是JavaScript的异步编程模式,为繁重的异步回调带来了福音. 一直以来,JavaScript处理异步都是以callback的方式,假设需要进行一个异步队列,执行起来如下: anim ...
- JavaScript Promise异步实现章节的下载显示
Links: JavaScript Promise:简介 1.一章一章顺序地下载显示下载显示 使用Array.reduce()和Promise.resolve()将各章的下载及显示作为整体串联起来. ...
- Javascript - Promise学习笔记
最近工作轻松了点,想起了以前总是看到的一个单词promise,于是耐心下来学习了一下. 一:Promise是什么?为什么会有这个东西? 首先说明,Promise是为了解决javascript异步编 ...
- Javascript Promise入门
是什么? https://www.promisejs.org/ What is a promise? The core idea behind promises is that a promise r ...
- JavaScript Promise API
同步编程通常来说易于调试和维护,然而,异步编程通常能获得更好的性能和更大的灵活性.异步的最大特点是无需等待."Promises"渐渐成为JavaScript里最重要的一部分,大量的 ...
- 【JavaScript】JavaScript Promise 探微
http://www.html-js.com/article/Promise-translation-JavaScript-Promise-devil-details 原文链接:JavaScript ...
随机推荐
- 我与OO (1)
前言 “真正的勇士敢于面对惨淡的人生,敢于面对淋漓的鲜血” 我是谨慎拜读了鲁迅先生的名言,怀着崇敬的精神去接触这门课程的. 而当我真的经历了这门课程以后,我才发现,刘和珍君这样的觉悟,我们普通人,果然 ...
- ImportError: No module named managers
代码: import os import cPickle as pickle filename = '../dftest.pkl' if(os.path.exists(filename)): w=op ...
- sql 判断两条数据库查询语句结果是否有重复
select 身份证号 from (select 身份证号 from 表1 where 考试名称= 'aaa'union allselect 身份证号 from 表2 where 考试名称= 'bbb ...
- [Docker] 写 Dockerfile 的最佳实践理论
指导方针 创建短暂的容器 意思是 container 可以停止和销毁,接着以最小化启动和配置进行重新构建和替换. 理解构建的上下文 使用 docker build ,当前工作环境称 ...
- 2019 AI CITY CHALLENGE
官网: https://www.aicitychallenge.org/ 基于来自交通,信号系统,基础设施和运输的传感器数据,存在使运输系统更智能的巨大机会.不幸的是,由于几个原因,进展受到限制 ...
- el-input的color修改无效问题
相信很多前端初学者跟我一样也遇到过el-input的color修改无效问题 如下图:我想把el-input里面的文字改成蓝色,但是使用总是失败 修改方法:打开调试界面,找到el-input对应的sty ...
- windows 下用命令来操作定时任务
cmd下定时执行命令可以使用 at 命令 或者 schtasks命令.at 语法:at +时间+运行程序schtasks语法:schtasks /creat /tn 设定定时运行的名字 /tr “运行 ...
- Unix/Linux系统的发展史
Unix/Linux系统相信是学编程的人都认识这两个系统.我们知道Unix要钱,而Linux免费,而且这两者之间的发展史是什么样的,是不是两者就是同一个东西呢? 我将会以时间的发展过程来一步步的给大家 ...
- Game Engine Architecture 7
[Game Engine Architecture 7] 1.SRT Transformations When a quaternion is combined with a translation ...
- Excel VBA 连接各种数据库(一) VBA连接MySQL数据库
本文参考[东围居士]的cnblog博文 Excel.VBA与MySQL交互 在自己机器上调试成功,把调试中遇到的问题一并写出了. 本文主要涉及: VBA中的MySQL环境配置 VBA连接MySQL ...