javascript promises的使用
javascript
使用promises
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promisess
一个Promise是一个对象,代表一个异步操作最终的成功或失败。由于大部分人是已经创建的promises的消费者,这个指引将先解释如何使用返回(创建好的)promise,然后再解释如何创建。
本质上,一个promise是一个异步函数返回的对象,你可以attach回调给这个对象,而不是传递callback函数给异步函数。
想象一个函数,createAudioFileAsync(), 它接收参数是一个配置记录和一个成功的回调函数,一个失败的回调函数,然后异步生成一个声音文件。
它的实现是这样的:
function successCallback(result) {console.log("Audio file ready at URL: " + result);
}
function failureCallback(error) {console.error("Error generating audio file: " + error);
}
createAudioFileAsync(audioSettings, successCallback, failureCallback);
然而现代语言是返回一个promise,然后你可以attach你的callback.
createAudioFileAsync用promise重写,它就会是如下简单:
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
它是下面的简写:
const promise = createAudioFileAsync(audioSettings);
promise.then(successCallback, failureCallback);
上面就是个异步函数调用,下面逐一介绍它的优点。
Guarantees保证
不象老式的传递回调函数,promise的下面几个保证:
在当前运行JavaScript事件循环的完成之前,永远不会调用回调。
callback通过then来添加,即使是在异步操作完成后(成功或失败),callback也保证会被调用,如前面的例子。
通过多次调用then来添加多个callback,每个callback会按顺序一个一个地调用。
可以使用chainning是使用promise的最大好处。
Chainning调用链
一个常用的事例是多个异步调用需要一个接一个地调用,后面的操作开始执行基于前面操作返回的结果。 这种我们可以通过promiss chain来完成。
这个魔术的原理是then返回一个新的promise,这是与原来不同的地方。
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
也可以写成
const promise2 = doSomething().then(successCallback, failureCallback);
promise2代表不仅是doSomething完成了,同样代表successCallback或failureCallback的完成,promise2可以是加外一个异步函数返回的promise. 这就是,任何添加在promise2之后的callback都会排在由successCallback
or failureCallback
返回的promise之后。
基本上,每个promise代表chain上的另外一个异步的完成。
在过去,连续执行几个异步操作会导致经典的回调金字塔:
doSomething(function(result) {doSomethingElse(result, function(newResult) {doThirdThing(newResult, function(finalResult) {console.log('Got the final result: ' + finalResult);}, failureCallback);}, failureCallback);
}, failureCallback);
现代的promise chain
doSomething()
.then(function(result) {return doSomethingElse(result);
})
.then(function(newResult) {return doThirdThing(newResult);
})
.then(function(finalResult) {console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
then的参数是可选的,而catch(failureCallback)
是 then(null, failureCallback)
的简写。
可以用lambda表达式.箭头函数
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);
重要: 必须返回结果,否则其它callbacks获取不到前一个promise的结果。 (with arrow functions () => x
is short for () => { return x; }
).
一个具体的promise chain:
new Promise(function(resolve, reject) {setTimeout(() => resolve(1), 1000); // (*)
}).then(function(result) { // (**)alert(result); // 1return result * 2;
}).then(function(result) { // (***)alert(result); // 2return result * 2;
}).then(function(result) {alert(result); // 4return result * 2;
});
分开调then的经典错误,下面是不会链式传递结果。
let promise = new Promise(function(resolve, reject) {setTimeout(() => resolve(1), 1000);
});
promise.then(function(result) {alert(result); // 1return result * 2;
});
promise.then(function(result) {alert(result); // 1return result * 2;
});
promise.then(function(result) {alert(result); // 1return result * 2;
});
上面直接返回结果,下面返回的是promise
new Promise(function(resolve, reject) {setTimeout(() => resolve(1), 1000);
}).then(function(result) {alert(result); // 1return new Promise((resolve, reject) => { // (*)setTimeout(() => resolve(result * 2), 1000);});
}).then(function(result) { // (**)alert(result); // 2return new Promise((resolve, reject) => {setTimeout(() => resolve(result * 2), 1000);});
}).then(function(result) {alert(result); // 4
});
具体看 https://javascript.info/promise-chaining
Chaining after a catch
用catch处理chain上失败的情况
new Promise((resolve, reject) => {console.log('Initial');//run
resolve();
})
.then(() => {throw new Error('Something failed');console.log('Do this');//not run
})
.catch(() => {console.error('Do that');//run
})
.then(() => {console.log('Do this, no matter what happened before');//run
});
输出如下:
Initial
Do that
Do this, no matter what happened before
错误传播Error propagation
你可能还记得,在之前末日金字塔(pyramid of doom)有三次失败回调,而在promise chain的末端,只有一次:
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log(`Got the final result: ${finalResult}`))
.catch(failureCallback);
如果链上有错误,浏览器就会往链下面 找 .catch()
or onRejected
。
Promises通过捕获所有错误,甚至抛出异常和编程错误,解决了回调金字塔的一个基本缺陷。这对于异步操作的功能组合至关重要。
Promise rejection events
当promise被 rejected时,下面两个event中的一个会发送到全局。(通常是window,或者web worker或者其它基于web worker的interface)
rejectionhandled
reject被处理后
unhandledrejection
reject未被处理
web开发者要学习下,我用nodejs跳过先。
为老的callback api封闭promise
例如旧的
setTimeout(() => saySomething("10 seconds passed"), 10*1000);
用promise
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback);
组合Composition
Promise.all()等所有的异步操作并行执行完毕。
Promise.all([func1(), func2(), func3()])
.then(([result1, result2, result3]) => { /* use result1, result2 and result3 */ });
顺序组合
[func1, func2, func3].reduce((p, f) => p.then(f), Promise.resolve())
.then(result3 => { /* use result3 */ });
与下面相等
Promise.resolve().then(func1).then(func2).then(func3);
javascript promises的使用相关推荐
- 初识JavaScript Promises
JavaScript有很多槽点,嵌套回调怕是千夫所指. 很久之前,我一直使用async来处理JavaScript异步编程中的嵌套回调问题.当然我也大概的了解过一些其它旨在解决这些问题的类库,诸如Eve ...
- JavaScript Promises
上篇文章介绍了JavaScript异步机制,请看这里. JavaScript异步机制带来的问题 JavaScript异步机制的主要目的是处理非阻塞,在交互的过程中,会需要一些IO操作(比如Ajax请求 ...
- [转]JavaScript/Node.JS 中的 Promises
JavaScript Promises 初体验 Promise 是什么? Promise 对象用来进行延迟(deferred) 和 异步(asynchronous) 计算. 一个 Promise 处于 ...
- JavaScript中的HTTP GET请求?
我需要在JavaScript中执行HTTP GET请求. 最好的方法是什么? 我需要在Mac OS X破折号小部件中执行此操作. #1楼 上面有很多很棒的建议,但不是很可重用,并且经常被DOM废话和其 ...
- javascript闭包_通过邮寄包裹解释JavaScript闭包
javascript闭包 by Kevin Kononenko 凯文·科诺年科(Kevin Kononenko) 通过邮寄包裹解释JavaScript闭包 (JavaScript Closures E ...
- javascript 应用_如何利用JavaScript的功能使您的应用脱机工作
javascript 应用 In today's world, connectivity has made us more mobile than ever which (paradoxically) ...
- javascript测试_了解有关JavaScript承诺的更多信息:25次测试中从零到英雄
javascript测试 by Andrea Koutifaris 由Andrea Koutifaris 了解有关JavaScript承诺的更多信息:25次测试中从零到英雄 (Learn more a ...
- JavaScript进阶之路——认识和使用Promise,重构你的Js代码
2019独角兽企业重金招聘Python工程师标准>>> 一 .初识Promise 1.什么是promise? Promise可能大家都不陌生,因为Promise规范已经出来好一段时 ...
- 程序员必须掌握的 12 个 JavaScript 技能!
本文论述的12个概念,对于 JavaScript 开发者来说都是非常重要的. 作者 | Nick Scialli 译者 | 谭开朗 责编 | 屠敏 出品 | CSDN(ID:CSDNNews) 以下为 ...
最新文章
- 活动报名 | MSRA卢帅:自动化代码审查过程的研究
- grid - 使用相同的名称命名网格线和设置网格项目位置
- 使用SQL DTS功能实现从DB/2向SQL Server传输数据
- 测试oracle删除干净,彻底卸载Oracle
- 【Win32汇编】__declspec(naked)裸函数
- hydra mysql 爆破_Hydra(爆破神器)使用方法
- 将某字符串切割成阵列并排序列出
- easyui table 如何只展示一条_如何使用MySQL,这些操作你得明白!
- 实验一 Linux开发环境的配置 20145213祁玮 20145222黄亚奇
- 泛微OA系统远程命令执行漏洞
- 【软件与系统安全】笔记与期末复习
- JVM 内存分析神器 MAT: Shallow Heap Vs Retained Heap 你理解的对吗?
- Java UTC时间戳
- I帧和IDR帧区别(转载)
- 利用CSS设置文字的阴影效果
- SQL 中GUID的使用
- Flutter 新一代图形渲染器 Impeller
- Office 365导出PDF带备注页
- Centos7学习——echo命令
- ES进阶之路二(ES7-ES12)