天天看点

正确的姿势,快速了解一下掌握promise

谈到promise,首先大家应该了解promise的主要作用是解决异步加载的问题。

##关于异步

所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

比如,有一个任务是读取文件进行处理,任务的第一段是向操作系统发出请求,要求读取文件。然后,程序执行其他任务,等到操作系统返回文件,再接着执行任务的第二段(处理文件)。这种不连续的执行,就叫做异步。

相应地,连续的执行就叫做同步。由于是连续执行,不能插入其他任务,所以操作系统从硬盘读取文件的这段时间,程序只能干等着。简单的说同步就是大家排队工作,异步就是大家同时工作。 ##Promise A+规范的 Promise 为了便于理解,本文将分为三个部分,每个部分实现 Promise 的一部分特性,最终一步一步的实现一个完整的、遵循 promise A+ 规范的 Promise。Promise A+ 规范规定,Promise 有三种状态,分别是 pending(默认状态,代表等待)、fulfilled(代表成功)、rejected(代表失败)。来看看 Promise 的用法,以及它有哪些特性。 var fn = new Promise(function (resolve, reject) {

// 异步操作

setTimeout(function() {

resolve('111')

// 由于reslove和 reject 是互斥的,因为已经调用了 resolve,这里reject不会执行 reject('111') }, 500) }) fn.then(function (data) { console.log('成功1:', data) return new Promise(function (resolve, reject) { reject('reject 02') } )}, function (err) { console.log('失败1:', err) }) .then(function (data) { console.log('成功2:', data) }, function (err) { console.log('失败2:', err) }).then(function (data) { console.log('成功2:', data)}, function (err) { console.log('失败2:', err) })

通过以上输出结果,我们可以得出以下几个结论。

1.Promise 类有 then 方法,then 方法有三个参数,分别是 Promise 成功和失败的回调以及pending初始状态

2.Promise 支持链式调用,then 的返回值可以是一个 Promise,也可以是一个普通值,如果是 一个普通的值,那么就会当做下一个 then 成功的回调函数的参数

3.Promis 还有其它扩展方法

##接下来我们简单了解一下promise的一些封装原理

class Promise {

constructor(executor) { //定义初始状态 this.status = 'pending'; this.value = undefined; this.reason = undefined; this.onResolvedCallbacks = []; this.onRejectedCallbacks = [];

//返回成功回调函数

let resolve = (data) => { // 加载数据判断成功 if (this.status === 'pending') { this.value = data; this.status = 'resolved'; this.onResolvedCallbacks.forEach(fn => fn()); } }

let reject = (reason) => { // 加载数据判断失败 if (this.status === 'pending') { this.reason = reason; this.status = 'rejected'; this.onRejectedCallbacks.forEach(fn => fn()); } }`

try { executor(resolve, reject); } catch (e) { reject(e); } }

then(onFulFilled, onRejected) { onFulFilled = typeof onFulFilled === 'function' ? onFulFilled : y => y; onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err; }; let promise2; if (this.status === 'resolved') { promise2 = new Promise((resolve, reject) => { setTimeout(() => { try { let x = onFulFilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); } if (this.status === 'rejected') { promise2 = new Promise((resolve, reject) => { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e); } }, 0); }); } if (this.status === 'pending') { promise2 = new Promise((resolve, reject) => { this.onResolvedCallbacks.push(() => { setTimeout(() => { try { let x = onFulFilled(this.value); resolvePromise(promise2, x, resolve, reject) } catch (e) { reject(e); } }, 0) }); // 存放失败的回调 this.onRejectedCallbacks.push(() => { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); }) } return promise2; // 调用then后返回一个新的promise } // catch接收的参数 只用错误 catch(onRejected) { // catch就是then的没有成功的简写 return this.then(null, onRejected); } }

Promise.resolve = function (val) { return new Promise((resolve, reject) => resolve(val)) }

Promise.reject = function (val) { return new Promise((resolve, reject) => reject(val)); }

了解了promise的原理,接下来给你们扩展一下promise番外篇,async-await函数和Generator 函数

1.Generator 函数

Genrator 函数要用* 来比标识,yield关键字表示暂停。将函数分割出好多个部分,调用一次next就会继续向下执行。返回结果是一个迭代器,迭代器有一个next方法。

function* read() { console.log(1); let a = yield '123'; console.log(a); let b = yield 9 console.log(b); return b; } let it = read(); console.log(it.next('213')); // {value:'123',done:false} console.log(it.next('100')); // {value:9,done:false} console.log(it.next('200')); // {value:200,done:true} console.log(it.next('200')); // {value:200,done:true}

yield后面跟着的是value的值,yield等号前面的是我们当前调用next传进来的值,并且第一次next传值是无效的。

处理异步的时候Generator和Promise搭配使用

let bluebird = require('bluebird'); let fs = require('fs'); let read = bluebird.promisify(fs.readFile);//将readFile转为Promise对象的实例 function* r() { let content1 = yield read('./2.promise/1.txt', 'utf8'); let content2 = yield read(content1, 'utf8'); return content2; }

2.async-await函数

let bluebird = require('bluebird'); let fs = require('fs'); let read = bluebird.promisify(fs.readFile);

async function r(){ try{ let content1 = await read('./2.promise/100.txt','utf8'); let content2 = await read(content1,'utf8'); return content2; }catch(e){ // 如果出错会catch console.log('err',e) } }

以上是我对promise的理解,希望有什么错误可以指正。

继续阅读