const p = new Promise((resolve, reject) => {
resolve('ok')
})
const result = p.then((value) => {
return new Promise((resolve, reject) => {
// 1,返回成功的promise
//resolve('success')
// 2, 返回失败的promise
reject('error')
})
})
result
前言
Promise是ES6引入的进行异步编程的新的解决方案, 从语法上来说,它就是一个构造函数,可封装异步的任务并且可以对结果进行处理,它最大的好处就是可以解决异步回调地域的问题,并且它的指定回调在进行错误处理这块要更加的灵活和方便. 它在现代的项目中, 无论是web还是app的项目当中,都应用的十分广泛.无论是前端还是后端都可以看到Promise的身影. 它也是现代面试的高频题目,所以必须掌握Promise运行的原理.如果你还对Promise的用法不了解,可以查看阮一峰老师的ES6 Promise教程。
- Promise的介绍
理解
- Promise是ES6规范
- Promise是JS进行异步编程的解决方案(旧方案是回调函数)一个异步操作并可以获取其成功/失败的结果
异步编程(旧方案回调函数)
(1)fs文件操作
require(fs).readfile('.index.html', (err, data) => {})
(2)数据库操作
(3)AJAX
$.get('server', (data) => {})
(4)定时器
setTimeout(()=>{},0)
- 从语法上来说, 它就是一个构造函数,
- 从功能上来说,Promise对象用来封装, 提供统一的接口,使得控制异步操作更加容易.
- Promise缺点:
- 无法取消Promise, 一旦新建它就会立即执行, 无法中途取消.
- 其次,如果不设置回调函数,Promise内部抛出的错误, 不会反应到外部.
- 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
Promise特点
1,Promise的状态
实例对象中的一个属性 [PromiseState]
对象的状态不受外界影响, Promise对象代表一个异步操作, 有三种状态
- pending: 初始状态, 不是成功或失败状态.
- resolved / fulfilled: 操作成功状态
- rejected: 操作失败状态
2,Promise 对象的值
实例对象中的另一个属性[PromiseResult]
保存着异步任务对象 [成功/失败] 的结果 - resolve
- reject 3,一旦状态改变, 就不会再变Promise对象的状态改变, 只有两种可能:
- 从pending -> fulfilled
- 从pending -> rejected
说明:
一个Promise对象只能改成一次, 无论成功还是失败.
成功的结果一般称为value, 失败的结果一般称为reason
就算改变已经发生结果, 再对Promise对象添加回调函数, 也会立即得到这个结果.
这与事件(Event)完全不同, 事件的特点是, 你错过了它, 再去监听, 是得不到结果的.
为何使用Promise
- 指定回调函数的方式更加灵活
- 旧的,必须在启动异步任务前指定
$.get('server', (data) => {
//执行内容
//得先指定回调函数
})
- Promise,启动异步任务=>返回Promise对象=>给Promise对象绑定回调函数(可以在异步任务结束后指定多个)
var p = new Promise((resolve, reject) => {
// 执行内容
setTimeout(() =>{
resolve('成功')
})
})
// 在启动任务后指定回调函数
p.then((val)=>{},(err) => {})
.then((val) => {},(err)=>{})
.then((val) => {},(err)=>{})
.....
- 支持链式调用,解决回调地域的问题
// 回调地域
test1(...arg1) =>{
test2(...arg2)=> {
test3(...arg3) => {
// 更多函数
}
}
}
- 回调地域的缺点: 不便于阅读,不便于异常错误处理
- 解决回调地域问题: Promise链式调用
Promise执行流程
1.Promise 基本执行图
- 构造函数创建, executer执行器立即同步执行
2.Promise 详细执行流程图 (备注, resolved状态就是fulfilled状态)
var p = new Promise ((resolved, rejected) =>{})
p.then((onResolved, onRejected))
.cacth(onRejected)
3.Promise 事件轮询执行图 (此处只提起带过, 如果你还对Event Loop事件轮询不了解, 可以查看这篇文章)
fn(resolve, reject)
var p = new Promise(fn)
var p' = p.then(onFufilled1, onRejected1)
var p" = p'.then(onFufilled2, onRejected2)
var p2 = new Promise(fn)
var p2' = p2.then(onFufilled1, onRejected1)
var p2" = p2'.then(onFufilled2, onRejected2)
Promise基本使用
function rand (m, n) {
return Math.ceil(Math.random()* (n-m+1)) + m-1;
}
/*Promise 形式实现
* resolve 解决 函数类型的数据
* reject 拒绝 函数类型的数据
* */
const p = new Promise(((resolve, reject) => {
setTimeout(() => {
const n = rand(1, 100) //获取 1-100的随机整数
if (n < 30) {
resolve(n) //将Promise的状态 设置为成功
} else {
reject(n) // 将Promise的状态 设置为失败
}
}, 500)
}))
p.then((value) => {
console.log(value + '这是0-30的值')
}, (reason) => {
console.log(reason + '这是30-90的值')
})
Promise API
1. Promis构造函数: Promise(executer){}
(1)executer函数: 执行器 (resolve, reject) =>{}
(2)resolve函数: 内部定义成功时我们调用的函数 value => {}
(3)reject函数: 内部定义失败时我们调用的函数 reason =>{}
说明: executor还会在Promise内部立即同步调用, 异步操作在执行器中执行
2. Promise.prototype.then方法: (onResolved, onRejected) =>{}
(1) onResolved函数: 成功的回调函数 (value) =>{}
(2) onRejected函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功/失败的回调, 返回一个新的Promise对象
3. Promise.prototype.catch方法(onRejected) => {}
(1) onRejected函数: 失败的回调函数 (reason) =>{}
说明: then()的语法糖, 相当于then(undefined, onRejected)
4. Promise.resolve方法 : (value) => {}
(1) value: 成功的数据或promise对象
说明:属于Promise的函数对象, 不属于实例,返回一个成功/失败的promise对象
// 如果传入的参数为非Promise类型的对象, 则返回的结果为成功promise对象
// 如果传入的参数promise对象, 则参数的结果决定了resolve的结果
const p1 = Promise.resolve(521)
const p2 = Promise.resolve(new Promise((resolve,reject) => {
reject('失败')
}))
5. Promise.reject方法: (reject) => {}
(1) reason: 失败的原因
说明: 返回一个失败的promise对象
// 不管传入的参数是什么类型, 返回的都是失败的Promise对象
const p1 = Promise.reject(521)
const p2 = Promise.reject(new Promise((resolve,reject) => {
resolve('成功')
}))
// 处理浏览器报错异常
p1.catch((reason) => {})
p2.catch((reason) => {})
6. Promise.all方法: (promises) => {}
- promsies: 包含n个promises的数组
- 返回一个新的promise
- 全部成功, 状态才返回成功 PromiseResult结果为返回值组成的数组
- 只要有一个失败了就直接失败, 返回最先失败的Promise的结果和状态
const p1 = new Promise((resolve,reject) => {
setTimeout(() => {
resolve('成功')
}, 1000)
})
const p2 = Promise.resolve('p2-成功')
const p3 = Promise.resolve('p3-成功')
Promise.race([p1,p2,p3])
7. Promise.race方法: (promises) => {}
(1)promises: 包含n个promises的数组
说明: 返回一个新的promise. 第一个完成的promise的结果状态就是最终的结果状态.
Promise 关键问题 (封装前必须注意的问题)
1. 如何改变Promise的状态
- resolve(value): 如果当前是pending就会变为resolved
- reject(reason): 如果当前是pending就会变成rejected
- 抛出异常: 如果当前是pending就会变成rejected
const p = new Promise((resolve, reject) => {
// 1.resolve函数
//resolve('ok') // pending => fulfilled(resolved)
// 2.reject 函数
//reject('error') // pending => rejected
// 3. 抛出错误
throw '出问题了'
})
2. 一个promise指定多个成功/失败回调函数, 都会调用吗?
当promise改变为对应状态时都会调用
const p = new Promise((resolve, reject) => {
resolve('OK')
})
p.then((value) => {
console.log(value + '第一个回调函数')
})
p.then((value) => {
console.log(value + '第二个回调函数')
})
3. 改变promsise状态和指定回调函数谁先谁后(执行)?
(1)都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
(2)如何先改状态再指定回调?
- 在执行器中直接调用 resolve()/reject()
- 延迟更长时间才调用then() (3) 什么时候才得到数据?
- 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用,得到数据
- 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
// 代码层面这样理解, 是resolve这个改变状态方法先执行, 还是then这个回调先执行
const p = new Promise((resolve, reject) => {
// 1. 当是同步任务的时候, 是先改变状态, 在执行then
// resolve('ok')
// 2,当是异步任务的时候, 是先执行then, 再改变状态
setTimeout(() =>{
resolve('ok')
})
})
p.then((value) => {
console.log(value)
})
4. promise.then()返回新的promise的结果状态由什么决定?
- (1)总结: 由then指定的回调函数执行的结果决定
- (2)详细表达:
- 如果抛出异常, 新promise变为rejected, reason为抛出的异常
- 如果返回的是, 非promsie的任意值, 新promise变为resolved, value为返回的值
- 如果返回的是另一个新的promise, 此promise的结果就会变成新promise的结果
5. promise如何串联多个操作任务?
- promise的then()返回一个新的promise. 可以开成then()的链式调用
- 通过then的链式调用串联多个同步/异步任务
6. promise异常穿透
- 当使用promise的then链式调用时, 可以在最后指定失败的回调
- 前面任何操作除了异常,都会传到最后的失败的回调中处理
const p = new Promise((resolve, reject) => {
resolve('ok')
})
p.then((value) =>{
throw '出错了'
}).then((value) =>{
console.log(value)
}).catch((reason) => {
// 结果输出->' 出错了'
console.log(reason)
})
7. 中断promise链
- 当使用promise的then链式调用时, 在中间中断, 不再调用后面的回调函数
- 方法: 在回调函数中返回一个pedding状态的promise对象
const p = new Promise((resolve, reject) => {
resolve('ok')
})
p.then((value) =>{
// 中断promise链
return new Promise((resolve, reject) => {})
}).then((value) => {
console.log(value + '不会执行')
})
Promise 自定义封装
说明:封装的思路->了解Promise的所有思想, 根据原来的Promise->实现自己的Promise
1. 初始结构搭建 (定义promise函数和原型上的then函数)
class Promise {
constructor (executer) {
executer()
}
then() {}
}
2. 实现Promise内部执行器函数调用的resolve和reject方法
class Promise {
// 定义Promise属性
PromiseState = 'pending'
PromiseResult = null
constructor (executer) {
// 注意 [状态的值只能改变一次]
// 改变对象的状态 [PromiseState]
// 改变对象的值 [PromiseResult]
let resolve = (value) => {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'fulfilled'
this.PromiseResult = value
}
let reject = (reason) => {
if (this.PromiseState !== 'pending') return
this.PromiseResult = reason
this.PromiseState = 'rejected'
}
// 处理抛出异常 throw
try {
executer(resolve, reject)
}catch (e) {
reject(e)
}
}
then() {}
}
// new 封装的Promise
const p = new Promise((resolve, reject) => {
resolve('ok')
// reject('error')
// throw '出错了'
})
console.log(p)
- 这里看下结果, 接下来就不会每一层都看结果, 你可以尝试reject和throw输出结果
- 输出原生Promise结果
3. 实现-同步调用then
- 返回值是 promsie
- 状态改变马上同步调用then()
- 调用onResolved()和onRejected()回到函数
- then的结果和状态 根据回调函数onResolved()和onRejected()的返回值决定
class Promise {
// 定义Promise属性
PromiseState = 'pending'
PromiseResult = null
// 构造函数上面已经实现, 这里省略, 可以查看第2点, 最后会给出全部的代码
constructor (executer) {...}
// 两个回调 onResolved onRejected
then(onResolved, onRejected) {
// then 返回一个新的promise
return new Promise((resolve, reject) => {
// 状态是成功
if (this.PromiseState === 'fulfilled') {
//传入PromiseResult then的结果和状态 根据它的返回值决定
let res = onResolved(this.PromiseResult)
// 1. 返回值是Promise
if (res instanceof Promise) {
res.then(v =>{
resolve(v)
}, r => {
reject(r)
})
}else {
// 2.返回值是非Promise -> 直接返回成功
resolve(res)
}
}
// 状态是失败, 传入PromiseResult
if(this.PromiseState === 'rejected') {
//传入PromiseResult then的结果和状态 根据它的返回值决定
let res = onRejected(this.PromiseResult)
// 1. 返回值是Promise
if (res instanceof Promise) {
res.then(v =>{
resolve(v)
}, r => {
reject(r)
})
}else {
// 2.返回值是非Promise -> 直接返回成功
resolve(res)
}
}
})
}
}
4. 实现-异步调用then
- 返回值是 promsie
- promise状态为pending, 先同步执行then,将回调函数存储(存储多个, promise可以有多个回调)
- 在异步函数执行完成以后, resolve/reject中改变状态
- 调用存储的回调函数
- try catch捕获错误
- 提取funType 公共代码
class Promise {
// 定义Promise属性
PromiseState = 'pending'
PromiseResult = null
// 存储then的回调函数
callbacks = []
constructor (executer) {
// 注意 [状态的值只能改变一次]
// 改变对象的状态 [PromiseState]
// 改变对象的值 [PromiseResult]
let resolve = (value) => {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'fulfilled'
this.PromiseResult = value
// 异步状态改变以后, 调用回调函数
this.callbacks.forEach((item) =>{ item.onResolved() })
}
let reject = (reason) => {
if (this.PromiseState !== 'pending') return
this.PromiseResult = reason
this.PromiseState = 'rejected'
// 异步状态改变以后, 调用回调函数
this.callbacks.forEach((item) =>{ item.onRejected() })
}
// 处理抛出异常 throw
try { executer(resolve, reject) }
catch (e) { reject(e) }
}
// 两个回调 onResolved onRejected
then(onResolved, onRejected) {
// then 返回一个新的promise
return new Promise((resolve, reject) => {
// 提取公共代码
let funType = (type)=>{
try {
let res = type(this.PromiseResult)
if(res instanceof Promise) {
res.then(v => { resolve(v) }, r => { reject(r) })
} else {resolve(res) } // 返回非promise 直接返回成功
}catch (e) {
reject(e)
}
}
// 传入PromiseResult, then的结果和状态,根据funType的返回值决定
// 状态是成功
if (this.PromiseState === 'fulfilled') { funType(onResolved) }
// 状态是失败,
// 传入PromiseResult
if(this.PromiseState === 'rejected') { funType(onRejected) }
// 状态为pending 存储onResolved和onRejected函数->到callback属性
if(this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: () => { funType(onResolved) },
onRejected: () =>{ funType(onRejected) }
})
}
})
}
}
5. catch方法
- catch方法是then的语法糖
class Promise {
// 定义Promise属性
PromiseState = 'pending'
PromiseResult = null
// 存储then的回调函数
callbacks = []
constructor (executer) {... }
// 两个回调 onResolved onRejected
then(onResolved, onRejected) { ... }
// 增加catch方法
catch(onRejected) {
return this.then(undefined, onRejected)
}
}
6. 异常穿透和值传递
- 可以允许不传onResolved/onRejected实参
- 实现: 不传参数时,内部定义一个函数
if (typeof onResolved !== 'function') {
// 成功 函数没有定义时, 直接传值
onResolved = value => value
}
if(typeof onRejected !== 'function') {
// 失败 函数没有定义时, 直接抛出错误
onRejected = (reason) =>{
throw reason
}
}
7. then回调函数异步执行
- then方法是异步执行的, 得等同步代码执行完以后
- 左侧代码是我们封装的, 右侧是原生的Promise
- 实现自己分装的Promise可以异步执行
- 实现方法: 在代码中,调用 onResovled和onRejected函数时, 增加setTimeout
8. 封装的Promise构造函数和原型链上then方法所有源码
class Promise {
// 定义Promise属性
PromiseState = 'pending'
PromiseResult = null
// 存储then的回调函数
callbacks = []
constructor (executer) {
// 注意 [状态的值只能改变一次]
// 改变对象的状态 [PromiseState]
// 改变对象的值 [PromiseResult]
let resolve = (value) => {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'fulfilled'
this.PromiseResult = value
// 异步状态改变以后, 调用回调函数
this.callbacks.forEach((item) =>{
setTimeout(() => {
item.onResolved()
})
})
}
let reject = (reason) => {
if (this.PromiseState !== 'pending') return
this.PromiseResult = reason
this.PromiseState = 'rejected'
// 异步状态改变以后, 调用回调函数
this.callbacks.forEach((item) =>{
setTimeout(() => {
item.onRejected()
})
})
}
// 处理抛出异常 throw
try {
executer(resolve, reject)
}
catch (e) {
reject(e)
}
}
// 两个回调 onResolved onRejected
then(onResolved, onRejected) {
// 成功 函数没有定义时, 直接传值
if (typeof onResolved !== 'function') {
onResolved = value => value
}
// 失败 函数没有定义时, 直接抛出错误
if(typeof onRejected !== 'function') {
onRejected = (reason) =>{
throw reason
}
}
// then 返回一个新的promise
return new Promise((resolve, reject) => {
// 提取公共代码
let funType = (type)=>{
try {
if (typeof type !== 'function') return
let res = type(this.PromiseResult)
if(res instanceof Promise) {
res.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {// 返回非promise 直接返回成功
resolve(res)
}
}catch (e) {
reject(e)
}
}
// 传入PromiseResult, then的结果和状态,根据funType的返回值决定
// 1. 状态是成功
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
funType(onResolved)
})
}
// 2. 状态是失败
if(this.PromiseState === 'rejected') {
setTimeout(() => {
funType(onRejected)
})
}
// 状态为pending 存储onResolved和onRejected函数->到callback属性
if(this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: () => { funType(onResolved)},
onRejected: () =>{ funType(onRejected) }
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
}
9. Promise函数对象->resolve方法
- 不属于实例对象
- 使用 static关键字声明 静态方法(属于Promise函数)
static resolve (value) {
return new Promise((resolve, reject) =>{
// 同then方法的判断
if (value instanceof Promise) {
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
10. Promise函数对象->reject方法
static reject (reason) {
// 永远返回失败的Promise
return new Promise((resolve, reject) => {
reject(reason)
})
}
11. Promise函数对象->all方法
static all (promises) {
// 返回一个新的promise,
// 全部成功, 状态才返回成功 PromiseResult结果为返回值组成的数组
// 如果失败, 则返回最先失败的Promise的结果和状态
// 按顺序存储返回的结果, 不管同步还是异步
return new Promise((resolve, reject) => {
let arr = []
let num = 0
for(let i= 0; i< promises.length; i++) {
promises[i].then(v => {
num++
arr[i] = v
// 只有当最后一个promise成功且走到这里, 代表全部成功
if (num === promises.length) {
resolve(arr)
}
}, r =>{
reject(r)
})
}
})
}
12. Promise函数对象->race方法
static race (promises) {
// 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态
return new Promise((resolve, reject) => {
for(let i= 0; i< promises.length; i++) {
promises[i].then( v => {
resolve(v)
}, r =>{
reject(i)
})
}
})
}
anync与await
anync
- async 函数 和 Promise的then方法规则一样
- 返回一个Promise
- 它的结果和状态是由函数的返回值决定
async function test () {
return 'ok'
}
test()
// test函数返回的是一个Promise
await表达式
- await右侧表达式 一般称为Promise对象, 也可以直接是值
- 如果表达式是Promise, 则返回的是成功的Promise的值
- 如果表达式是其他值, 直接将此值返回
- await 必须写在async函数中,但async函数中, 可以没有await
- 如果await 的promise失败了,会抛出异常, 需要通过 try...catch处理
anync和await结合使用
- Promise 实际上是利用编程技巧将回调函数改成链式调用,避免回调地狱。最大问题是代码冗余,原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆 then,原来的语义变得不太清楚。
- 这里使用async和await, 语义看上去比较清晰.
// 需要在node和环境下使用
// 练习 读取one和two两个文件夹的内容
const fs = require('fs')
const util = require('util')
const mineReadFile = util.promisify(fs.readFile) // 返回一个Promise
async function readFile() {
try{
const d1 = await mineReadFile('./resource/one.txt')
const d2 = await mineReadFile('./resource/two.tx')
console.log(d1 + d2)
}catch (e) {
console.log(e)
}
}
readFile()
封装Promise的代码
class Promise {
// 定义Promise属性
PromiseState = 'pending'
PromiseResult = null
// 存储then的回调函数
callbacks = []
constructor (executer) {
// 注意 [状态的值只能改变一次]
// 改变对象的状态 [PromiseState]
// 改变对象的值 [PromiseResult]
let resolve = (value) => {
if (this.PromiseState !== 'pending') return
this.PromiseState = 'fulfilled'
this.PromiseResult = value
// 异步状态改变以后, 调用回调函数
this.callbacks.forEach((item) =>{
setTimeout(() => {
item.onResolved()
})
})
}
let reject = (reason) => {
if (this.PromiseState !== 'pending') return
this.PromiseResult = reason
this.PromiseState = 'rejected'
// 异步状态改变以后, 调用回调函数
this.callbacks.forEach((item) =>{
setTimeout(() => {
item.onRejected()
})
})
}
// 处理抛出异常 throw
try {
executer(resolve, reject)
}
catch (e) {
reject(e)
}
}
// 两个回调 onResolved onRejected
then(onResolved, onRejected) {
// 成功 函数没有定义时, 直接传值
if (typeof onResolved !== 'function') {
onResolved = value => value
}
// 失败 函数没有定义时, 直接抛出错误
if(typeof onRejected !== 'function') {
onRejected = (reason) =>{
throw reason
}
}
// then 返回一个新的promise
return new Promise((resolve, reject) => {
// 提取公共代码
let funType = (type)=>{
try {
if (typeof type !== 'function') return
let res = type(this.PromiseResult)
if(res instanceof Promise) {
res.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {// 返回非promise 直接返回成功
resolve(res)
}
}catch (e) {
reject(e)
}
}
// 传入PromiseResult, then的结果和状态,根据funType的返回值决定
// 1. 状态是成功
if (this.PromiseState === 'fulfilled') {
setTimeout(() => {
funType(onResolved)
})
}
// 2. 状态是失败
if(this.PromiseState === 'rejected') {
setTimeout(() => {
funType(onRejected)
})
}
// 状态为pending 存储onResolved和onRejected函数->到callback属性
if(this.PromiseState === 'pending') {
this.callbacks.push({
onResolved: () => { funType(onResolved)},
onRejected: () =>{ funType(onRejected) }
})
}
})
}
catch(onRejected) {
return this.then(undefined, onRejected)
}
static resolve (value) {
return new Promise((resolve, reject) =>{
// 同then方法的判断
if (value instanceof Promise) {
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
} else {
resolve(value)
}
})
}
static reject (reason) {
// 永远返回失败的结果
return new Promise((resolve, reject) => {
reject(reason)
})
}
static all (promises) {
// 返回一个新的promise,
// 全部成功, 状态才返回成功 PromiseResult结果为返回值组成的数组
// 如果失败, 则返回最先失败的Promise的结果和状态
// 按顺序存储返回的结果, 不管同步还是异步
return new Promise((resolve, reject) => {
let arr = []
let num = 0
for(let i= 0; i< promises.length; i++) {
promises[i].then(v => {
num++
arr[i] = v
// 只有当最后一个promise成功且走到这里, 代表全部成功
if (num === promises.length) {
resolve(arr)
}
}, r =>{
reject(r)
})
}
})
}
static race (promises) {
// 返回一个新的promise, 第一个完成的promise的结果状态就是最终的结果状态
// 按顺序存储返回的结果, 不管同步还是异步
return new Promise((resolve, reject) => {
for(let i= 0; i< promises.length; i++) {
promises[i].then( v => {
resolve(v)
}, r =>{
reject(r)
})
}
})
}
}