Promise 用法

Posted wgchen~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Promise 用法相关的知识,希望对你有一定的参考价值。

promise是什么?

1、主要用于异步计算

2、可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果

3、可以在对象之间传递和操作promise,帮助我们处理队列

为什么会有promise?

为了避免界面冻结(任务)

同步:
假设你去了一家饭店,找个位置,叫来服务员,这个时候服务员对你说,对不起我是“同步”服务员,我要服务完这张桌子才能招呼你。

那桌客人明明已经吃上了,你只是想要个菜单,这么小的动作,服务员却要你等到别人的一个大动作完成之后,才能再来招呼你,这个便是同步的问题:也就是“顺序交付的工作1234,必须按照1234的顺序完成”。

异步:
则是将耗时很长的A交付的工作交给系统之后,就去继续做B交付的工作。
等到系统完成了前面的工作之后,再通过回调或者事件,继续做A剩下的工作。
AB工作的完成顺序,和交付他们的时间顺序无关,所以叫“异步”。

有了nodeJS之后…
对异步的依赖进一步加剧了

大家都知道在nodeJS出来之前php、Java、python等后台语言已经很成熟了,nodejs要想能够有自己的一片天,那就得拿出点自己的绝活:

无阻塞高并发,是nodeJS的招牌,要达到无阻塞高并发异步是其基本保障

举例:
查询数据从数据库,PHP第一个任务查询数据,后面有了新任务,那么后面任务会被挂起排队;

而nodeJS是第一个任务挂起交给数据库去跑,然后去接待第二个任务交给对应的系统组件去处理挂起,接着去接待第三个任务…那这样子的处理必然要依赖于异步操作。

promise 是一个对象

promise 是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)

并未剥夺函数return的能力,因此无需层层传递callback,进行回调获取数据

代码风格,容易理解,便于维护

多个异步等待合并便于解决

promise详解

new Promise(
  function (resolve, reject) {
    // 一段耗时的异步操作
    resolve('成功') // 数据处理完成
    // reject('失败') // 数据处理出错
  }
).then(
  (res) => {console.log(res)},  // 成功
  (err) => {console.log(err)} // 失败
)

resolve 作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;

reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

promise有三个状态:

1、pending [待定] 初始状态

2、fulfilled [实现] 操作成功

3、rejected [被否决] 操作失败

当promise状态发生改变,就会触发 then() 里的响应函数处理后续步骤;

promise状态一经改变,不会再变。

Promise对象的状态改变,只有两种可能:

pending 变为 fulfilled

pending 变为 rejected

这两种情况只要发生,状态就凝固了,不会再变了。

Promise 解决回调地狱

Promise 用法

Promise 概述

Promise 是异步编程的一种解决方案,从语法上讲,Promise 是一个对象,从它可以获取异步操作的消息。

ES6 Promise

ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范。作为ES6中最重要的特性之一,我们有必要掌握并理解透彻。本文将由浅到深,讲解Promise的基本概念与使用方法。

console.dir(Promise)


使用 Promise 主要有以下好处:

可以避免多层异步调用嵌套问题(回调地狱)

Promise 对象提供了简洁API,使得控制异步操作更加容易

Promise 基本用法

实例化 Promise 对象,构造函数中传递函数,该函数中用于处理异步任务

resolvereject 两个参数用于处理成功和失败两种情况,并通过 p.then 获取处理结果

var p = new Promise(function(resolve,reject){
	// 成功时调用 resolve()
	// 失败时调用 reject()
});

p.then(function(ret){
	// 从 resolve 得到正常结果
},function(ret){
	// 从 reject 得到错误信息
});

示例

<script>
var p=new Promise(function(resolve,reject){
    //这里用户实现异步任务
    setTimeout(function(){
        var flag=false;
        if(flag){
            //正常情况
            resolve('hello');
        }else{
            //异常情况
            reject('出错了');
        }
    },1000);
}); 
//hello传递给了data
p.then(function(data){
    //打印正常信息
    console.log(data);
},function(info){
    //打印异常信息
    console.log(info);
});
</script>

一秒后打印:

Promise基于原生ajax发送请求,php并设置跨域

<script>
//Promise基于原生ajax发送请求
function queryData(url){
    var p=new Promise(function(resolve,reject){
        var xhr=new XMLHttpRequest();
        xhr.onreadystatechange=function(){
            if(xhr.readyState!=4) return;
            if(xhr.readyState==4 && xhr.status==200){
                //处理正常的情况
                resolve(xhr.responseText);
            }else{
                //处理异常的情况
                reject('服务器错误');
            }
        };
        xhr.open('get',url);
        xhr.send(null);
    });
    return p;
}
queryData("http://dcatadmin.cc/user").then(function(data){
    var obj = JSON.parse(data); //SON字符串转换成对象
    console.log(obj);
    alert(obj.name);
},function(info){
    console.log(info);
});
</script>

php

<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
//主要为跨域CORS配置的两大基本信息,Origin和headers
$arr=[
    'name'=>'willem',
    'age'=>'30',
    'sex'=>'男'
];

echo json_encode($arr);

laravel

public function getIndex()
{
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');

    //主要为跨域CORS配置的两大基本信息,Origin和headers
    $arr=[
        'name'=>'willem',
        'age'=>'30',
        'sex'=>'男'
    ];

    return response()->json($arr);
}

预览

基于 Promise 处理Ajax请求

queryData()
	.then(function(data){
		return queryData();
	})
	.then(function(data){
		return queryData();
	})
	.then(function(data){
		return queryData();
	});

发送多次 ajax 请求

then 参数中的函数返回值

1、返回 Promise 实例对象
返回的该实例对象会调用下一个then

2、返回普通值
返回的普通值会直接传递给下一个 then,通过 then 参数中函数的参数接收该值

<script>
//Promise基于原生ajax发送请求
function queryData(url)
{
    var p=new Promise(function(resolve,reject)
	{
        var xhr=new XMLHttpRequest();
		
        xhr.onreadystatechange=function()
		{
            if(xhr.readyState!=4) return;
			
            if(xhr.readyState==4 && xhr.status==200)
			{
                //处理正常的情况
                resolve(xhr.responseText);
            }else{
                //处理异常的情况
                reject('服务器错误');
            }
        };
		
        xhr.open('get',url);
        xhr.send(null);
    });
	
    return p;
}

queryData("http://dcatadmin.cc/user").then(function(data){
    var obj = JSON.parse(data); //SON字符串转换成对象
    console.log(obj);
    return queryData("http://dcatadmin.cc/user");
},function(info){
    console.log(info);
}).then(function(data){
    var obj = JSON.parse(data); //SON字符串转换成对象
    console.log(obj);
    return 123;
}).then(function(data){
    console.log(data);
});

</script>

Promise 常用 API

1、实例方法

p.then()得到异步任务的正确结果
p.catch 获取异常信息
p.finally()成功与否都会执行(尚且不是正式标准)

queryData()
	.then(function(data){
		console.log(data);
	})
	.catch (function(data){
		console.log(data);
	})
	.finally(function(data){
		console.log(data);
	});
<script>
function foo()
{
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            //resolve(123);
            reject('error');
        },1000);
    });
}

foo().then(function(data){
        console.log(data);
     })
     .catch(function(data){
        console.log(data+' cuo wu catch');
     })
     .finally(function(){
         console.log('finished');
     });
    
</script>

3、 对象方法

Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果
Promise.race() 并发处理多个异步任务,只要有一个任务完成就能得到结果

Promise.all([p1,p2,p3]).then((result)=>{
	console.log(result)
})

Promise.race([p1,p2,p3]).then((result)=>{
	console.log(result)
})
<script type="text/javascript">
/*Promise常用API-对象方法*/
function queryData(url)
{
    var p=new Promise(function(resolve,reject)
			{
				var xhr=new XMLHttpRequest();
				
				xhr.onreadystatechange=function()
				{
					if(xhr.readyState!=4) return;
					if(xhr.readyState==4 && xhr.status==200){
						//处理正常的情况
						resolve(xhr.responseText);
					}else{
						//处理异常的情况
						reject('服务器错误');
					}
				};
				xhr.open('get',url);
				xhr.send(null);
			});
		
	return p;
}

var p1=queryData("http://dcatadmin.cc/user");
var p2=queryData("http://dcatadmin.cc/res");

Promise.all([p1,p2]).then(function(result){
   console.log(result);
});

/*
Promise.race([p1,p2]).then(function(result){
    console.log(result);
});
*/
</script>

<?php

namespace App\\Http\\Controllers;

use App\\User;
use Illuminate\\Http\\Request;
use Illuminate\\Support\\Facades\\App;

class TestController extends Controller
{
    public function __construct()
    {
        header('Access-Control-Allow-Origin: *');
        header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept');
    }
    public function getIndex()
    {
        //主要为跨域CORS配置的两大基本信息,Origin和headers
        $arr=[
            'name'=>'willem',
            'age'=>'30',
            'sex'=>'男'
        ];

        return response()->json($arr);
    }
    public function res()
    {
        $users = User::all()->toArray();
        return response()->json($users);
    }
}

fetch 概述

1、基本特性

更加简单的数据获取方式,功能更强大、更灵活,可以看做是 xhr 的升级版
基于Promise

2、语法结构

fetch(url).then(fn2)
		  .then(fn3)
		  ...
		  .catch(fn)
<script type="text/javascript">
/*fetch API基本用法*/
fetch('http://dcatadmin.cc/res').then(function(data){
    return data.text();//text返回的是Promise对象
}).then(function(data){
    console.log(data);//这是打印的真实数据
});

</script> 

3、fetch 请求参数

1、常用配置选项

method(String):HTTP 请求方法,默认为GET(GET、POST、PUT、DELETE)
body(String):HTTP的请求参数
headers(Object):HTTP的请求头,默认为 {}

 响应数据格式
text():将返回体处理成字符串类型
json():返回结果和JSON.parse(reponseText)一样

fetch('/abc',{
	method:'get'
}).then(data=>{
	return data.text();
}).then(ret=>{
	// 注意这里得到的才是最终的数据
	console.log(ret);
});

2、GET请求方式的参数传递

fetch('/abc?id=1').then(data=>{
	return data.text();
}).then(ret=>{
	// 注意这里得到的才是最终的数据
	console.log(ret);
});

fetch('/abc/2').then(data=>{
	method:'get'
}).then(ret=>{
	return data.text();
}).then(ret=>{
	// 注意这里得到的才是最终的数据
	console.log(ret);
});

Fetch 的 get 传参

<script type="text/javascript">
/*fetch API基本用法*/

/*这种形式$_GET['id']获取即可
fetch('http://localhost/fetch.php?id=33',{'method':'get'})
.then(function(data){
    return data.text();//text返回的是Promise对象
}).then(function(data){
    console.log(data);//这是打印的真实数据
});
*/

/*这种形式需要通过取余等与0方式*/
fetch('http://dcatadmin.cc/res?id=3&name=willem&sex=nan&age=31',{'method':'get'})
.then(function(data){
    return data.text(); //text返回的是Promise对象
}).then(function(data){
    console.log(data);  //这是打印的真实数据
});

<<

以上是关于Promise 用法的主要内容,如果未能解决你的问题,请参考以下文章

前端面试题之手写promise

promise的用法

ES6 Promise用法讲解

promise用法详解

promise之nodejsQ的详细用法总结

是否存在无意义的Promise用法?