文章内容输出来源:拉勾教育 大前端高薪训练营

前言

在ES6中,新增加了一种异步编程的解决方案Promise,它是一种规范,是一套处理JavaScript异步的机制

Promise的含义

简单来说,它是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,通过它可以获取异步操作的消息。

Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。

Promise 对象有两个特点:

1、对象的状态不受外界影响。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。

Promise对象的状态改变,只有两种可能:
* 从 pending 变为 fulfilled;
* 从 pending 变为 rejected。

Promise的基础用法

Promise是一个类,它的构造函数中需要一个执行器作为参数传入进去,当使用Promise创建promise实例时,执行器会立即执行。在执行器中需要两个函数作为参数传递,即 resolve 和 reject 函数,这两个函数主要是用来更改状态的。
resolve 函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject 函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

  • 类核心逻辑的实现

下面我们来模拟一下Promise的类核心逻辑的实现。

代码如下(示例):(promise.js)

// 定义Promise构造函数// 定义promise的三种状态
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class Promise {// 传入执行器, 创建实例时,立即执行constructor (executor) {executor(this.resolve, this.reject);}status = PENDING;    // 初始化状态 为 pending  等待value = undefined;   // 保存成功之后的值reason = undefined;  // 保存失败后的原因resolve = value => {// 如果状态不是等待,阻止程序向下执行if (this.status !== PENDING) return// 将状态更改为成功 pending --> fulfilledthis.status = FULFILLED// 保存成功之后的值, 传入的值this.value = value}reject = reason => {// 如果状态不是等待,阻止程序向下执行if (this.status !== PENDING) return;// 将状态更改为失败 pending --> rejectedthis.status = REJECTED;// 保存失败后的原因,传入的原因this.reason = reason;}
}
module.exports = Promise;

创建实例 代码如下(示例):(index.js)

// 引入 promise 模块
const Promise = require('./promise')
// 创建 Promise实例,返回 promise对象
let promise = new Promise((resolve, reject) => {resolve(111);
})
console.log(promise);
/*Promise:{status: 'fulilled',value: 111,reason: undefined, resolve: [Function: resolve],reject: [Function: reject]}
*/

在上面的代码中,我们已经通过代码创建了 Promise构造函数,并通过调用构造函数创建了 promise实例,且返回了一个 promise对象。那么,实例创建成功以后,我们如何指定resolved状态和rejected状态的回调函数呢?

Promise.prototype.then()

在 Promise的原型对象中定义了一个then方法,then方法主要做的事情就是判断状态,如果状态是成功的,那么调用成功的回调函数;如果状态是失败的,那么调用失败的回调函数。而要调用then方法,必须返回一个 promise对象,在上面的代码中,我们已经实现了返回 promise对象。 then方法有两个参数:一个是成功回调函数,它接收一个参数,表示成功之后的值;二是失败回调函数,它也接收一个参数,表示失败后的原因。

下面让我们来看一下 then方法 的基础实现过程。

代码如下(示例):(promise.js)

// 重复代码以下使用 ...... 代替
......
class Promise {......then (successCallback, failCallback) {if (this.status === FULFILLED) {// 成功回调函数,将传入resolve函数中传入的值进行传入successCallback(this.value)  } else if (this.status === REJECTED) {// 失败回调函数,将传入reject函数中传入的原因进行传入failCallback(this.reason)}}
}

调用then方法 代码如下(示例):(index.js)

let promise = new Promise((resolve, reject) => {resolve(111);
})
promise.then(value => console.log(value), reason => console.log(reason))
// 打印:1111

在上面的代码中,由于我们在创建实例时,抛出的是成功的函数resolve,所以此时,then方法中执行的是成功的回调函数,此时value的值为resolve中保存的值,即value = 111,所以打印出111。

自此,我们已经完成了基本的 Promise的类核心逻辑。但是我们只是进行了同步的操作,并没有引入异步的逻辑,而在前面我们也讲到Promise主要就是为了解决异步操作的。

那么,我们接下来看一下,Promise是如何处理异步操作的?

代码如下(示例):(promise.js)

......
class Promise {......// 成功回调successCallback = undefined// 失败回调failCallback = undefinedresolve = value => {......// 此时是只调用一次then方法的写法// 判断成功回调是否存在 如果存在 调用this.successCallback && this.successCallback(this.value)}reject = reason => {......// 此时是只调用一次then方法的写法// 判断失败回调是否存在 如果存在 调用this.failCallback && this.failCallback(this.reason);}then (successCallback, failCallback) {if (this.status === FULFILLED) {successCallback(this.value)  } else if (this.status === REJECTED) {failCallback(this.reason)} else { // 等待期 // 处理异步操作/* 添加定时器(异步操作),导致 promise的状态进入等待期。1、如果我们不将成功回调和失败回调存储起来,那么定时器中的resolve(100)或者reject('error'),将不会被执行;2、需要在resolve和reject函数中判断成功回调和失败回调是否存在,存在时才会被调用*/// 此时是只调用一次then方法的写法this.successCallback = successCallback; this.failCallback = failCallback;}}
}

代码如下(示例):(index.js)

let promise = new Promise((resolve, reject) => {setTimeout(() => {resolve(111)// reject('error')}, 2000)
})
promise.then(value => console.log(value), reason => console.log(reason))
console.log(promise); // 此时处于等待期
// console.log(promise) 是处于主线程中的方法,会立即执行, 因此,打印顺序如下
/* -- 打印结果:Promise:{status: 'pending',value: undefined,reason: undefined, successCallback: [Function],   failCallback: [Function],resolve: [Function: resolve],reject: [Function: reject]}111
*/

在上面的代码中,我们是通过将成功回调和失败回调存储起来的方法,来解决Promise中的异步操作的。在上述代码中,我们只调用了一次 then方法,但其实同一个promise对象下面的then方法是可以被多次调用添加多个处理函数的。并且,当then方法被多次调用时,每一个then方法都是要被执行的。

代码如下(示例):(promise.js)

......
class Promise {......successCallback = [] // 多次调用,储存多个成功回调函数failCallback = []    // 多次调用,储存多个失败回调函数resolve = value => {......// 此时是多次调用then方法的写法while (this.successCallback.length) {this.successCallback.shift()(this.value)}}reject = reason => {......// 此时是多次调用then方法的写法while (this.failCallback.length) {this.failCallback.shift()(this.reason)}}then (successCallback, failCallback) {if (this.status === FULFILLED) {successCallback(this.value)  } else if (this.status === REJECTED) {failCallback(this.reason)} else { // 等待期 // 处理异步操作/*当我们多次调用then方法时,我们应该将每一次的成功回调和失败回调都储存起来因此,我们应该使用数组的形式,储存每一次调用then方法后指定的成功回调和失败回调*/// 此时多次调用then方法的写法this.successCallback.push(successCallback);this.failCallback.push(failCallback);}}
}

代码如下(示例):(index.js)

......
// 调用三次 then方法
promise.then(value => console.log(value), reason => console.log(reason))
promise.then(value => console.log(value), reason => console.log(reason))
promise.then(value => console.log(value), reason => console.log(reason))console.log(promise); // 此时处于等待期
/* -- 打印结果:Promise:{status: 'pending',value: undefined,reason: undefined, successCallback: [ [Function], [Function], [Function] ],   failCallback: [ [Function], [Function], [Function] ], resolve: [Function: resolve],reject: [Function: reject]}111111111
*/

在上面的代码中,我们展示了同一个 Promise对象调用多次 then方法添加多个处理函数的情况。但是有时在实际开发中,我们在调用下一个then方法时,我们需要借助上一个then方法中的返回值,这有点类似我们在上面所说的回调嵌套,在上面我们说到,如果使用回调函数的写法,很容易导致 回调地域 的情况的发生。那么,我们在 Promise中是否有办法解决这个问题呢?
其实,在 Promise是提供了这样的功能的,就是利用 then方法的链式调用。下面,我们就来具体的看一下 then方法的链式调用的实现。

  • 为了节省篇幅,以下代码,只分析 成功时的情况,最后会补全失败和等待期的代码

  • 首先,我们先来看一下 then方法中值传递的情况。

代码如下(示例):(promise.js)

......
class Promise {....../* -- 逻辑分析:1、调用 then方法的,必须是一个 Promise对象,因此在执行then方法后,需要返回一个promise对象;2、我们需要把上一个then方法中的回调函数的返回值传递给下一层then方法的回调函数, 因此我们需要,调用执行完上一个then方法后,返回的新的 promise2对象中的执行器中的resolve函数             */then (successCallback, failCallback) {// 1. 实现了 让then方法返回 promise对象// 传入执行器, 立即执行let promise2 = new Promise((resolve, reject) => { if (this.status === FULFILLED) {// 2. 实现把上一个then方法中的回调函数的返回值传递给下一层then方法的回调函数                let x = successCallback(this.value)   // x = 111// x 为成功回调函数的返回值,并将其传递给下一层then方法的回调函数中// 调用 resolve(x)方法,把上一层then方法返回的值传递给下层then方法的成功回调函数resolve(x)} else if (this.status === REJECTED) {// 失败回调函数,将传入reject函数中传入的原因进行传入failCallback(this.reason)} else {// 等待期this.successCallback.push(successCallback);this.failCallback.push(failCallback);}})return promise2;}
}

代码如下(示例):(index.js)

let promise = new Promise((resolve, reject) => {resolve(111);
})
promise.then(value => {console.log(value)    // 111return 1;
}).then(value => { console.log(value) // 1return value
}).then(value => console.log(value))   // 1.then(value => console.log(value))   // undefined

注意 要想实现 then方法的链式调用,上一层的成功回调函数必须有 return 返回值,否则,下层then方法是获取不到上层then方法中的返回值的。

由于在成功函数和失败函数以及等待期时,执行的操作应该是相同的操作,那么,在下面我们将单独封装一个函数,实现代码重用,减少代码冗余。

  • 下面我们再来看一下,then方法中返回 promise对象的情况。

代码如下(示例):(promise.js)

......
class Promise {......then (successCallback, failCallback) {// 1. 实现了 让then方法返回 promise对象let promise2 = new Promise((resolve, reject) => { if (this.status === FULFILLED) {               let x = successCallback(this.value)  // 判断 x 的值是 普通值 还是 promise对象 封装函数resolvePromise(x, resolve, reject)} else if (this.status === REJECTED) {               failCallback(this.reason)} else {// 等待期this.successCallback.push(successCallback);this.failCallback.push(failCallback);}})return promise2;}
}function resolvePromise (x, resolve, reject) {/** -- 逻辑分析* 判断 x 的值是 普通值 还是 promise对象* 如果是普通值,直接调用 resolve* 如果是 promise对象 查看 promise对象返回的结果* 再根据 promise 对象返回的结果 决定调用 resolve  还是调用 reject*/if (x instanceof Promise) { // x 是promise的情况/* x 的打印情况Promise:{status: 'fulfilled',value: 'new promise',reason: undefined, successCallback: [ [Function], [Function], [Function] ],   failCallback: [ [Function], [Function], [Function] ], resolve: [Function: resolve],reject: [Function: reject]}*/// x.then(value => resolve(value), reason => reject(reason))x.then(resolve, reject) // 代码简化} else { // x 是 值 的情况resolve(x)}
}

代码如下(示例):(index.js)

function other () {return new Promise((resolve, reject) => { resolve('new promise') })
}
let promise = new Promise((resolve, reject) => { resolve(111) })
promise.then(value => {console.log(value); // 111return other();
}).then(value =>  console.log(value) }) // new promise

在上面的代码中,我们是单独创建了一个新的 promise对象进行返回的。但我们在使用的时候可以看到,如果返回当前的 promise对象,会出现下面的错误。

代码如下(示例):(test.html)

 let promise = new Promise(function (resolve, reject) { resolve(100) });let p1 = promise.then(value => {console.log(value);return p1; }) p1.then(value => console.log(value) }, reason => console.log(reason))

报错信息:


那么,我们该如何识别 promise对象自返回呢?

代码如下(示例):(promise.js)

......
class Promise {......then (successCallback, failCallback) {let promise2 = new Promise((resolve, reject) => { if (this.status === FULFILLED) {   /* 由于这里属于程序运行过程中,而promise2是在程序执行完成后创建的,因此,我们可以将下面的代码使用定时器转换为异步代码。由于我们使用定时器只是为了转换,不是为了延时,因此我们需要将时间设为0*/setTimeout(() => {            let x = successCallback(this.value)  resolvePromise(promise2, x, resolve, reject)}} else if (this.status === REJECTED) {               failCallback(this.reason)} else {// 等待期this.successCallback.push(successCallback);this.failCallback.push(failCallback);}})return promise2;}
}function resolvePromise(promise2, x, resolve, reject) {// 判断是否是自己调用自己, 如果识别了 promise对象在自返回,那么我们模拟需要抛出下面的错误,并使用 return 阻止程序往下运行if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>')); }......
}

在上面的代码中,我们的代码其实并不完善,很多可能发生的错误并没有被捕获,那么下面我们来对代码进行一下补充和完善,使它用起来更加健壮。

代码如下(示例):(promise.js)

// 定义promise的三种状态
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class Promise {constructor(executor) {// 捕获执行器的错误try {executor(this.resolve, this.reject);} catch (e) {this.reject(e)}}status = PENDING;value = undefined;reason = undefined;successCallback = [];failCallback = [];resolve = value => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valuewhile (this.successCallback.length) {this.successCallback.shift()() // 在成功回调函数中已经进行了操作,因此就不用再传值了}}reject = reason => {if (this.status !== PENDING) return;this.status = REJECTED;this.reason = reason;while (this.failCallback.length) {this.failCallback.shift()() // 在失败回调函数中已经进行了操作,因此就不用再传值了}}then(successCallback, failCallback) {let promise2 = new Promise((resolve, reject) => {if (this.status === FULFILLED) {                setTimeout(() => {try {    let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {                let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e)}}, 0)} else {// 等待期this.successCallback.push(() => {setTimeout(() => {try {let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject);} catch (e) {// 调用下一个promise的reject回调函数reject(e);}}, 0)})this.failCallback.push(() => {setTimeout(() => {try {let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0)})}})return promise2;}}function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));}if (x instanceof Promise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = Promise;

代码如下(示例):(index.js)

const Promise = require('./promise')
let promise = new Promise((resolve, reject) => {setTimeout(() => {resolve(111)}, 2000)// throw new Error('executor error')// resolve(111)// reject('error')
})
promise.then(value => {console.log(value);   // 2秒以后,111return 'aaa';
}, reason => {console.log(reason); // throw new Error('then error')return 111;
}).then(value => console.log(value))  // 'aaa'

截至到目前为止,我们已经完成了 Promise类的核心逻辑,但是在上面所写的 then方法中,我们所传入的参数是必须要传入的,否则后面执行的then方法是无法获取到值的。

代码如下(示例):(index.js)

let promise = new Promise((resolve, reject) => {resolve(111)
})
promise.then().then(value => console.log(value))  // 未进行值传递,没有打印

那么,我们如何将 then方法中的参数变成可选参数,以便当不传递参数时,promise状态会依次向下传递,直到传递给有回调函数的then方法?

代码如下(示例):(promise.js)

......
class Promise {......then (successCallback, failCallback) {// 判断successCallback是否存在,// 如果存在时,等于原值;如果不存在,则将值往下进行传递// failCallback 同理successCallback = successCallback ? successCallback : value => value; failCallback = failCallback ? failCallback : reason => reason; ......}
}

代码如下(示例):(index.js)

let promise = new Promise((resolve, reject) => {resolve(111)
})
promise.then().then(value => console.log(value))  // 进行值传递,打印:111

讲到这里,我们已经实现了 Promise的then方法,那么下面我们来介绍一个处理并发问题的API。

Promise.all()

Promise.all()用于将多个 Promise 实例,包装成一个新的 Promise 实例,并且作为返回值返回,且可以链式调用then方法。Promise.all() 允许异步代码按照异步代码调用的顺序,得到结果。并且接收一个数组作为参数,数组中元素的顺序一定是我们得到的结果的顺序。

特点:

1、在all方法中所有的promise对象的状态都是成功的,那么最后的结果就是成功的;
2、在all方法中存在一个promise对象的状态是失败的,那么最后的结果就是失败的。

下面,我们来模拟一下 all 方法的实现过程。

代码如下(示例):(promise.js)

......
class Promise {......static all(array) {// 一、首先需要返回一个 promise对象实例,并且传入一个生成器,立即执行let result = []; // 结果数组let index = 0;return new Promise((resolve, reject) => {/* 逻辑分析二、我们需要对传入的数组进行遍历三、需要判断数组中的每一项元素是 promise对象 还是普通值1、如果是普通值,那么直接放到结果数组中;2、如果是 promise对象,则需要先执行这个 promise对象,然后再把返回的结果放到结果数组中*/for (let i = 0; i < array.length; i++) {let current = array[i];if (current instanceof Promise) { // 传入的是 promise对象// 可以链式调用then方法current.then(value => addData(i, value), reason => reject(reason))} else { // 普通值addData(i, array[i])}}// 给结果数组赋值function addData (key, value) {result[key] = value;                /* 四、由于for循环的执行是很快的,如果传入的 promise对象中含有异步操作,那么很有可能结果数组中会出现空值的情况 即 [ '1', '2', <1 empty item>, 'p2' ]*/index++;// 等待所有异步操作都完成,才要执行resolveif (index === array.length) {resolve(result) // 结果数组进行赋值时,才会调用resolve, 使之执行顺序和传入顺序一致}}})}
}

代码如下(示例):(index.js)

function p1 () {return new Promise((resolve, reject) => {setTimeout(() => {resolve('p1')}, 2000)})
}
function p2 () {return new Promise((resolve, reject) => {resolve('p2')})
}Promise.all(['1', '2', p1(), p2(), 3]).then(value => {console.log(value);   // [ '1', '2', 'p1', 'p2', 3 ]
})

在上面的代码中,我们都是自己创建的 promise对象。那么,有没有一个方法可以将普通的值或对象等转换成 promise对象呢?
其实,在Promise类中是提供了这样一个方法的,即 Promise.resolve()。

Promise.resolve()

Promise.resolve()的作用,就是将给定的值转换成 promise对象,也就是说,返回值就是一个 promise对象。

接下来我们来看一下,resolve()方法的代码实现过程。

代码如下(示例):(promise.js)

......
class Promise {......static resolve (value) {/*判断 value 是 promise对象,还是普通值如果是 promise对象,则直接返回如果是 普通值,使用resolve将传入的值进行包裹,然后返回这个新建的 promise对象*/ if (value instanceof Promise) {return value;} else {return new Promise(resolve => resolve(value));}}
}

代码如下(示例):(index.js)

function p2 () {return new Promise((resolve, reject) => {resolve('p2')})
}Promise.resolve(1).then(value => console.log(value)) // 1
Promise.resolve(p2()).then(value => console.log(value)) // p2

Promise.prototype.finally()

finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。

  • 特点

1、无论 promise对象最终的状态是成功的还是失败的,finally方法中的回调函数始终都会被执行一次;
2、可以在 finally方法的后面链式调用then方法,拿到这个 promise对象最终返回的结果。

代码如下(示例):(promise.js)

.....
class Promise {......finally (callback) {/* 逻辑分析无论当前promise的状态成功还是失败,都要执行callback这个回调函数首先,要获取当前 promise对象的状态,可以通过then方法获取;然后,需要在finally方法的后面链式调用then方法,要返回一个 promise对象因此可以直接返回then方法返回的 promise对象;接着,需要再次调用then方法,需要拿到当前then方法中promise对象的结果,并将其return最后,如果promise对象返回的结果中包含异步逻辑,而此时then方法可能不会等到异步操作执行完成,就直接执行了那么需要使用 Promise.resolve()方法,查看一下callback中的返回值,是普通值 还是 promise对象, 无论是什么,都等待其完成*/return this.then(value => {return Promise.resolve(callback()).then(() => value);}, reason => {// 传递错误原因return Promise.resolve(callback()).then(reason => { throw reason });})}......
}

代码如下(示例):(index.js)

function p1 () {return new Promise((resolve, reject) => {setTimeout(() => {resolve('p1')}, 2000)})
}
function p2 () {return new Promise((resolve, reject) => {resolve('p2')})
}
p2().finally(() => {console.log('finally');return p1();  // return 100;
}).then(value => {console.log(value);
}, reason => {console.log(reason);
})

Promise.prototype.catch()

catch方法用来处理当前 promise对象最终的状态为失败的情况的,内部注册的只有失败回调,成功回调返回undefined。

代码如下(示例):(promise.js)

catch (failCallback) {return this.then((undefined, failCallback))
}

代码如下(示例):(index.js)

function p2 () {return new MyPromise((resolve, reject) => {resolve('p2')})
}
p2().then(value => console.log(value)).catch(reason => console.log(reason))

总结

在上面的代码中,我们详细分析了Promise 底部核心逻辑的实现过程。最后在此附上全部的代码,希望对看到这篇文章的朋友们有所帮助。

代码如下(示例):(promise.js)

// 定义promise的三种状态
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class Promise {constructor(executor) {try {executor(this.resolve, this.reject);} catch (e) {this.reject(e)}}status = PENDING;value = undefined;reason = undefined;successCallback = [];failCallback = [];resolve = value => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valuewhile (this.successCallback.length) {this.successCallback.shift()() }}reject = reason => {if (this.status !== PENDING) return;this.status = REJECTED;this.reason = reason;while (this.failCallback.length) {this.failCallback.shift()() }}then(successCallback, failCallback) {successCallback = successCallback ? successCallback : value => value;failCallback = failCallback ? failCallback : reason => reason;let promise2 = new Promise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject)} catch (e) {reject(e)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e)}}, 0)} else {this.successCallback.push(() => {setTimeout(() => {try {let x = successCallback(this.value)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0)})this.failCallback.push(() => {setTimeout(() => {try {let x = failCallback(this.reason)resolvePromise(promise2, x, resolve, reject);} catch (e) {reject(e);}}, 0)})}})return promise2;}finally (callback) {return this.then(value => {return Promise.resolve(callback()).then(() => value);}, reason => {return Promise.resolve(callback()).then(reason => { throw reason });})}static all(array) {let result = [];let index = 0;return new Promise((resolve, reject) => {for (let i = 0; i < array.length; i++) {let current = array[i];if (current instanceof Promise) {current.then(value => addData(i, value), reason => reject(reason))} else {addData(i, array[i])}}function addData (key, value) {result[key] = value;     index++;if (index === array.length) {resolve(result) }}})}static resolve (value) {if (value instanceof Promise) {return value;} else {return new Promise(resolve => resolve(value));}}
}function resolvePromise(promise2, x, resolve, reject) {if (promise2 === x) { return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));}if (x instanceof Promise) {x.then(resolve, reject)} else {resolve(x)}
}
module.exports = Promise;

JavaScript异步编程【中】 -- Promise 详细解析相关推荐

  1. 【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)

    [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程.手写 Promise(课前准备) [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步 ...

  2. JavaScript异步编程【上】 -- 同步和异步、事件循环(EventLoop)、微任务和宏任务、回调函数

    文章内容输出来源:拉勾教育 大前端高薪训练营 前言 在我们学习JavaScript中,我们知道,JavaScript的执行环境是单线程的.所谓单线程是指一次只能完成一个任务,如果有多个任务,就必须排队 ...

  3. JavaScript 异步编程--Generator函数、async、await

    JavaScript 异步编程–Generator函数 Generator(生成器)是ES6标准引入的新的数据类型,其最大的特点就是可以交出函数的执行的控制权,即:通过yield关键字标明需要暂停的语 ...

  4. JavaScript异步编程原理

    众所周知,JavaScript 的执行环境是单线程的,所谓的单线程就是一次只能完成一个任务,其任务的调度方式就是排队,这就和火车站洗手间门口的等待一样,前面的那个人没有搞定,你就只能站在后面排队等着. ...

  5. JavaScript异步编程的原理

    1 想说的话 JavaScript异步编程是前端面试中一个重要内容.为了加深我对此部分内容的印象,故写此博客,主要介绍JS异步编程的运行原理. pre 栈队列 2 正文 本文主要是阐述下面这张图的内容 ...

  6. [书籍精读]《JavaScript异步编程》精读笔记分享

    写在前面 书籍介绍:本书讲述基本的异步处理技巧,包括PubSub.事件模式.Promises等,通过这些技巧,可以更好的应对大型Web应用程序的复杂性,交互快速响应的代码.理解了JavaScript的 ...

  7. 写给初学者的JavaScript异步编程和背后思想

    导读: 对于接触JavaScript这门编程语言没有多久的本菜鸡而言,在相当长的一段时间内,我都完全无法理解这门语言中的异步编程,不明白什么叫异步编程以及为什么需要异步编程.为什么顺序执行程序就不行了 ...

  8. Javascript异步编程之一异步原理

    本系列的例子主要针对node.js环境,但浏览器端的原理应该也是类似的. 本人也是Javascript新手,把自己这段时间学习积累的要点总结下来,希望可以对同样在学习Javascript/node.j ...

  9. 网页javascript加载不出_写给初学者的JavaScript异步编程和背后思想

    导读:对于接触JavaScript这门编程语言没有多久的本菜鸡而言,在相当长的一段时间内,我都完全无法理解这门语言中的异步编程,不明白什么叫异步编程以及为什么需要异步编程.为什么顺序执行程序就不行了呢 ...

  10. JavaScript异步编程【下】 -- Generator、Async/await

    文章内容输出来源:拉勾教育 大前端高薪训练营 前言 在JavaScript异步编程[上]和 JavaScript异步编程[中]中,我们已经讲到了处理异步编程的两种方法:回调函数 和 Promise. ...

最新文章

  1. VS2015智能提示由英文改为中文
  2. 047_Unicode对照表十三
  3. 深入java并发包源码(三)AQS独占方法源码分析
  4. restful API 常用的四种方式
  5. IOS AppUI规格指南
  6. 计算机二级是报office还是vb,请问一下计算机二级中,高阶office好考,还是VB好考?...
  7. Net设计模式实例之组合模式(Composite Pattern)(3)
  8. 每天花30分钟看OGRE--(13)Ogre的渲染流程,在渲染时材质是如何起作用的,材质加载和解析...
  9. 数控车宏程序c语言,a类宏程序什么意思?a类宏程序编程入门
  10. 关于我国高等数学教材的版权发财户
  11. 【源码】MATLAB的专业绘图工具
  12. js 华氏/摄氏转换
  13. 班长投票小程序的java代码
  14. 15个HTML5播放器插件
  15. Android之ANR
  16. 哪款蓝牙耳机音质好?内行推荐四款高音质蓝牙耳机
  17. Python tkinter 保姆级超简易登陆界面教学
  18. 如何将二维码数据换行显示
  19. R语言制作Meta分析偏倚风险评估(ROB)图
  20. Java网页数据抓取实例

热门文章

  1. smarty中js的调用方法
  2. const int *p与int *const p的区别
  3. LeetCode 617. Merge Two Binary Trees
  4. 字符流的抽象类 reader writter java
  5. Navicat Premium 12安装过程和相关资源
  6. django-模板语言-判断语句
  7. jquery-待办事列表-待整理
  8. SoapUI测试webservice
  9. 志翔科技用大数据技术为行业云构建“安全之翼”...
  10. alert.log中的minact-scn: useg scan erroring out with error e:376警告