来自 服务器&运维 2019-12-13 05:44 的文章
当前位置: 澳门威尼斯人平台 > 服务器&运维 > 正文

详解ES6 Promise对象then方法链式调用_javascript技巧_脚本之家

介绍

前言

promise俗称链式调用,它是es6中最重要的特性之一

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单来说就是一个容器,里面保存着某个未来才会结束的事件的结果。

第一次接触到Promise这个东西,是2012年微软发布Windows8操作系统后抱着作死好奇的心态研究用html5写Metro应用的时候。当时配合html5提供的WinJS库里面的异步接口全都是Promise形式,这对那时候刚刚毕业一点javascript基础都没有的我而言简直就是天书。我当时想的是,微软又在脑洞大开的瞎捣鼓了。

简单的说可以不停的then调用嵌套在调用,这种操作方式称为promise

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

缺少场景支撑,对于新手而言,很难理解Promise的意义。

结果没想到,到了2015年,Promise居然写进ES6标准里面了。而且一项调查显示,js程序员们用这玩意用的还挺high。

then()方法的作用是Promise实例添加解决和拒绝状态的回调函数。then()方法会返回一个新的Promise实例,所以then方法进行链式调用。

了解什么是 Promise 对象

在《你不知道的JavaScript中》有个场景介绍得很形象:

讽刺的是,作为早在2012年就在Metro应用开发接口里面广泛使用Promise的微软,其自家浏览器IE直到2015年寿终正寝了都还不支持Promise,看来微软不是没有这个技术,而是真的对IE放弃治疗了。。。

let p = new Promise => { setTimeout(resolve, 1000, 'success');});p.then( res => { console.log; return `${res} again`; }) .then( res => console.log;// 连续// success// success again

在项目中,会出现各种异步操作,如果一个异步操作的回调里还有异步操作,就会出现回调金字塔。

我走到快餐店的柜台,点了一个芝士汉堡。我交给收银员1.47美元。通过下订单并付款,我已经发出了一个对某个值的请求。我已经启 动了一次交易。

现在回想起来,当时看到Promise最头疼的,就是初学者看起来匪夷所思,也是最被js程序员广为称道的特性:then函数调用链。

但是前一个then()方法中的回调函数中又可能返回一个Promise实例,这时候后面一个then()方法中的回调函数会等前一个Promise实例的状态发生变化才会调用。

比如下面这种

但是,通常我不能马上就得到这个汉堡。收银员会交给我某个东西来代替汉堡:一张带有 订单号的收据。订单号就是一个 IOU承诺,保证了最 终我会得到我的汉堡。

then函数调用链,从其本质上而言,就是对多个异步过程的依次调用,本文就从这一点着手,对Promise这一特性进行研究和学习。

let p = new Promise => { setTimeout(resolve, 1000, 'success');});p.then( res => { console.log; return new Promise => { setTimeout(resolve, 1000, 'success'); }); }) .then( res => console.log;// 相隔1000ms// success// success
// 模拟获取code,然后将code传给后台,成功后获取userinfo,再将userinfo传给后台// 登录wx.login({ success: res => { let code = res.code // 请求 imitationPost({ url: '/test/loginWithCode', data: { code }, success: data => { // 获取userInfo wx.getUserInfo({ success: res => { let userInfo = res.userInfo // 请求 imitationPost({ url: '/test/saveUserInfo', data: { userInfo }, success: data => { console.log }, fail: res => { console.log }, fail: res => { console.log }, fail: res => { console.log }, fail: res => { console.log

所以我得好好保留我的收据和订单号。我知道这代表了我未来的汉堡,所以不需要担心, 只是现在我还是很饿!

Promise解决的问题

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

下面分析如何用Promise来进行简化代码

在等待的过程中,我可以做点其他的事情,比如给朋友发个短信:“嗨,要来和我一起吃 午饭吗?我正要吃芝士汉堡。”

考虑如下场景,函数延时2秒之后打印一行日志,再延时3秒打印一行日志,再延时4秒打印一行日志,这在其他的编程语言当中是非常简单的事情,但是到了js里面就比较费劲,代码大约会写成下面的样子:

因为微信小程序异步api都是success和fail的形式,所有有人封装了这样一个方法:

我已经在想着未来的芝士汉堡了, 尽管现在我还没有拿到手。 我的大脑之所以可以这么 做,是因为它已经把订单号当作芝士汉堡的占位符了。从本质上讲,这个占位符使得这个 值不再依赖时间。这是一个未来值。

var myfunc = function() { setTimeout { console.log; setTimeout { console.log; setTimeout { console.log; }, 3000); }, 2000);}

promisify.js

终于, 我听到服务员在喊“订单 113” , 然后愉快地拿着收据走到柜台, 把收据交给收银 员,换来了我的芝士汉堡。

由于嵌套了多层回调结构,这里形成了一个典型的金字塔结构。如果业务逻辑再复杂一些,就会变成令人闻风丧胆的回调地狱。

module.exports =  => { return  => { return new Promise => { api(Object.assign({}, options, { success: resolve, fail: reject }), ...params); }); }}

// 获取系统信息wx.getSystemInfo({ success: res => { // success console.log }, fail: res => { }})

换句话说, 一旦我需要的值准备好了, 我就用我的承诺值换取这个值 本身。

如果意识比较好,知道提炼出简单的函数,那么代码差不多是这个样子:

使用上面的promisify.js简化后:

但是,还可能有另一种结果。他们叫到了我的订单号,但当我过去拿芝士汉堡的时候,收 银员满是歉意地告诉我:“不好意思,芝士汉堡卖完了。”除了作为顾客对这种情况感到愤 怒之外,我们还可以看到未来值的一个重要特性:它可能成功,也可能失败。

var func1 = function() { setTimeout;};var func2 = function() { console.log; setTimeout;};var func3 = function() { console.log; setTimeout;};var func4 = function() { console.log;};
const promisify = requireconst getSystemInfo = promisifygetSystemInfo().then(res=>{ // success console.log

每次点芝士汉堡,我都知道最终要么得到一个芝士汉堡,要么得到一个汉堡包售罄的坏消息,那我就得找点别的当午饭了。

这样看起来稍微好一点了,但是总觉得有点怪怪的。。。好吧,其实我js水平有限,说不上来为什么这样写不好。如果你知道为什么这样写不太好所以发明了Promise,请告诉我。

getSystemInfo

所以Promise的出现其实是作为异步编程的一种解决方案。比传统的解决方案-回调函数和事件-更加合理、强大。

现在让我们言归正传,说说Promise这个东西。

可以看到简化后的回调里少了一个缩进,并且回调函数从9行减少到了6行。

Promise的基本用法

Promise的描述

回调金字塔的简化效果

var p1 = new Promise => { setTimeout(resolve, 1000, 'done'); })p1.then(data=>{ console.log

这里请允许我引用MDN对Promise的描述:

那么再来看看最开始的那个回调金字塔

Promise一个明显的好处便是可以用来解决回调地狱。特别是在处理多个回调相互依赖的情况。

Promise 对象用于延迟 计算和异步 计算.。一个Promise对象代表着一个还未完成,但预期将来会完成的操作。

const promisify = requireconst login = promisifyconst getSystemInfo = promisify// 登录login().then(res => { let code = res.code // 请求 pImitationPost({ url: '/test/loginWithCode', data: { code }, }).then(data => { // 获取userInfo getUserInfo().then(res => { let userInfo = res.userInfo // 请求 pImitationPost({ url: '/test/saveUserInfo', data: { userInfo }, }).then(data => { console.log.catch(res => { console.log.catch(res => { console.log.catch(res => { console.log.catch(res => { console.log

使用Promise解决多个异步依赖调用

Promise 对象是一个返回值的代理,这个返回值在promise对象创建时未必已知。它允许你为异步操作的成功或失败指定处理方法。 这使得异步方法可以像同步方法那样返回值:异步方法会返回一个包含了原返回值的 promise 对象来替代原返回值。

可以看到简化效果非常明显。

本文由澳门威尼斯人平台发布于服务器&运维,转载请注明出处:详解ES6 Promise对象then方法链式调用_javascript技巧_脚本之家

关键词: