本篇内容我们以访问“天气”为例,来简单的学习 Promise。
直奔主题:一般情况我们调用一次API就可以完成请求,有些情况我们需要反复调用服务器API,这就会形成一个链式调用,这个时候我们可能就会陷入回调带来的问题深渊。介时,我们就有必要依赖于异步进行操作,在nodeJs中,我们就会用到Promise。
一、Promise:
1、主要用于异步计算。
2、可以将异步操作队列化,按照期望的顺序执行,并返回符合预期的结果。
3、也可以在对象之间传递和操作promise,帮助我们处理队列。
4、promise是一个对象,可以保存状态。
5、没有剥夺函数return的能力,无需层层嵌套callback。
6、多个异步等待合并便于解决。
二、Promise中常见的属性:
1、resolve:将Promise对象的状态从“未完成”变成“成功”,在异步操作成功时被调用,并将异步操作的结果作为参数传递出去。
2、reject:将Promise对象的状态从“未完成”变成“失败”,在异步操作失败时被调用,并将异步操作报出的错误作为参数传递出去。
3、Promise会自动捕获内部异常,并交给rejected响应处理。
4、pending[待定]初始状态。
5、fulfilled[实现]操作成功。
6、rejected[被否决]操作失败。
用法:new Promise( function(resolve, reject){ } )
当Promise状态发生改变,就会触发then()里的响应函数处理;Promise状态一经改变不会再变;Promise状态的改变只会从pending->fulfilled 或 从pending变成 rejected。
7、.then()
(1)接收两个函数作为参数,分别代表fulfilled(成功)和rejected(失败)
(2).then()返回一个新的Promise实例,所以它可以链式调用
(3)当前面的Promise状态改变时,.then()根据其最终状态,选择特定的状态响应函数执行
(4)状态响应函数可以返回新的promise,或其他值,不返回值也可以我们可以认为它返回了一个null;
(5)如果返回新的promise,那么下一级.then()会在新的promise状态改变之后执行
(6)如果返回其他任何值,则会立即执行下一级.then()
(7).then()里面有.then()的情况 : 因为.then()返回的还是Promise实例,会等里面的then()执行完,再执行外面的
有了以上初步理论知识的基础,我们接下来学习异步查询天气。
首先我们创建一个 wetherSearch.js ,并创建同名的类:
class wetherSearch
{
//构造函数
constructor(){
this.cityName = ''
}
search(cityName, callBack)
{
this.cityName = cityName
console.log("city:", cityName);
}
}
module.exports = wetherSearch //被全局访问
接下来我们创建一个Api.js:
var wetherSearch = require('./wetherSearch.js') //引入上述文件
var wsInstance = new wetherSearch() //创建对象
wsInstance.search("胡忠市")
执行上述Api.js文件,我们可以在控制台上看到输出的内容。当然,这只是简单的创建了一个类,
跟我们的Promise没有任何关系。接下来我们就开始逐步假如Promise属性。
切入正题之前,我们还需要了解一下async和await,二者是成对出现的关键字, await必须放在async函数中使用。
async需要放置到函数名前面,用于表示函数是一个异步函数,也就意味着该函数的执行不会阻塞后面代码的执行。
用法: async function runTime(){ return ‘Hello’ }
需要注意的是: async函数返回的结果是一个Promise对象,这时,我们要学习的Promise就出现了。
await 顾名思义是等待的意思,它是在等待Promise对象执行完毕,然后拿到promise resolve 的值并返回,
返回值拿到之后,继续向下执行。
好了,初步了解了async和await,我们就可以开始代码操作了。
1、我们在上述代码search函数前面加上async ,
async search(cityName, callBack)
{
this.cityName = cityName
}
2、不要忘记刚刚说过的async返回的是一个Promise对象,所以我们需要将代码改成下面的格式:
async search(cityName, callBack)
{
this.cityName = cityName
return new Promise(function(resolve, reject){
})
}
3、基本结构以及呈现了,我们开始请求访问“天气”,说道请求,我们难免会想到request, 所以把 request引入进来。
var request = require('request')
访问“天气”的URL 大家可以打开网页搜索,本文以http://t.weather.sojson.com/api/weather/city/101170301为例,
101170301编码就是一个城市,每个城市都有唯一标识,所以search函数现在可以变成下面的格式:
async search(cityName, callBack)
{
this.cityName = cityName
return new Promise(function(resolve, reject){
request('http://t.weather.sojson.com/api/weather/city/101170301', function (error, response, body) {
var data = JSON.parse(body) //可以将body 输出,来看一下body格式和内容
var forecast = data.data.forecast //根据输出的body,获取forecast
我们将未来几天的日期、最高温度、最低温度 放入一个容器中。
var finalData = []
for(var i=0; i<forecast.length; i++)
{
var curWether = forecast[i]
var date = curWether.date
var low = curWether.low
var high = curWether.high
finalData.push({'date':date, 'low':low, 'high':high})
}
resolve(finalData) //不要忘记该函数的功能喽
})
})
}
好了,写了半天我们把访问的部分写好了,接下来我们看一看怎么获得访问的结果。
我们也需要将Api.js中的内容进行修改,与上述雷同,需要加入async和 await。
async function run(cityName) {
// 创建对象
var wsInstance = new wetherSearch()
//等待异步操作结果
var data = await wsInstance.search(cityName).catch(function (error){
console.log('error:',error)
})
//根据结果的不同,分别进行处理
if(data)
return Promise.resolve(data)
else
Promise.resolve(null)
}
获取结果的代码写过了,下面我们就开启一个简答的监听服务:
var express = require('express')
var app = express()
app.get('/search/:cityName', async function (req, res) {
var cityName = req.param("cityName")
var data = await run(cityName)
res.send(data)
})
app.listen(3000)
之后运行Api.js,并在网页中输入"http://localhost:3000/search/胡忠市" ,便可获得未来几天的气温情况。
好了,本课程的学习到此结束,希望能够对学者们有所帮助。