乐趣区

关于ecmascript:学习使用Promise

前言

最近在开发中遇到一个问题:Table 行内有下拉组件四级联动,而且还能够增加新行,每个新行又是四级联动,问:如何解决?想了半天于是应用 Promise 解决,让我从新对 Promise 有了意识。

Promise 详解

通过 MDN 官网文档对 Promise 有段介绍:Promise 对象用于示意一个异步操作的最终实现 (或失败) 及其后果值。

一个 Promise 对象代表一个在这个 promise 被创立进去时不肯定已知的值。它让您可能把异步操作最终的胜利返回值或者失败起因和相应的处理程序关联起来。这样使得异步办法能够像同步办法那样返回值:异步办法并不会立刻返回最终的值,而是会返回一个 promise,以便在将来某个时候把值交给使用者。

一个 Promise 必然处于以下几种状态之一:

  • 待定(pending): 初始状态,既没有被兑现,也没有被回绝。
  • 已兑现(fulfilled): 意味着操作胜利实现。
  • 已回绝(rejected): 意味着操作失败。

待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个起因(谬误)被回绝(rejected)。当这些状况之一产生时,咱们用 promise 的 then 办法排列起来的相干处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就曾经被兑现或被回绝了,那么这个处理程序就会被调用,因而在实现异步操作和绑定解决办法之间不会存在竞争状态。

因为 Promise.prototype.then 和 Promise.prototype.catch 办法返回的是 promise,所以它们能够被链式调用。


1、构造函数

Promise()
创立一个新的 Promise 对象。该构造函数次要用于包装还没有增加 promise 反对的函数。

2、静态方法

Promise.all(iterable)
这个办法返回一个新的 promise 对象,该 promise 对象在 iterable 参数对象里所有的 promise 对象都胜利的时候才会触发胜利,一旦有任何一个 iterable 外面的 promise 对象失败则立刻触发该 promise 对象的失败。这个新的 promise 对象在触发胜利状态当前,会把一个蕴含 iterable 里所有 promise 返回值的数组作为胜利回调的返回值,程序跟 iterable 的程序保持一致;如果这个新的 promise 对象触发了失败状态,它会把 iterable 里第一个触发失败的 promise 对象的错误信息作为它的失败错误信息。Promise.all 办法常被用于解决多个 promise 对象的状态汇合。(能够参考 jQuery.when 办法 — 译者注)

Promise.allSettled(iterable)
等到所有 promises 都已敲定(settled)(每个 promise 都已兑现(fulfilled)或已回绝(rejected))。
返回一个 promise,该 promise 在所有 promise 实现后实现。并带有一个对象数组,每个对象对应每个 promise 的后果。

Promise.any(iterable)
接管一个 Promise 对象的汇合,当其中的一个 promise 胜利,就返回那个胜利的 promise 的值。

Promise.race(iterable)
当 iterable 参数里的任意一个子 promise 被胜利或失败后,父 promise 马上也会用子 promise 的胜利返回值或失败详情作为参数调用父 promise 绑定的相应句柄,并返回该 promise 对象。

Promise.reject(reason)
返回一个状态为失败的 Promise 对象,并将给定的失败信息传递给对应的解决办法

Promise.resolve(value)
返回一个状态由给定 value 决定的 Promise 对象。如果该值是 thenable(即,带有 then 办法的对象),返回的 Promise 对象的最终状态由 then 办法执行决定;否则的话 (该 value 为空,根本类型或者不带 then 办法的对象), 返回的 Promise 对象状态为 fulfilled,并且将该 value 传递给对应的 then 办法。通常而言,如果您不晓得一个值是否是 Promise 对象,应用 Promise.resolve(value) 来返回一个 Promise 对象, 这样就能将该 value 以 Promise 对象模式应用。

应用 Promise

通过下面能够具体理解 Promise 的静态方法,起初就是应用 Promise 实例,

创立 Promise

Promise 对象是由关键字 new 及其构造函数来创立的。该构造函数会把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”承受两个函数——resolve 和 reject ——作为其参数。当异步工作顺利完成且返回后果值时,会调用 resolve 函数;而当异步工作失败且返回失败起因(通常是一个谬误对象)时,会调用 reject 函数。

const myFirstPromise = new Promise((resolve, reject) => {
  // ? 做一些异步操作,最终会调用上面两者之一:
  //
  //   resolve(someValue); // fulfilled
  // ? 或
  //   reject("failure reason"); // rejected
});

想要某个函数领有 promise 性能,只需让其返回一个 promise 即可。

function myAsyncFunction(url) {return new Promise((resolve, reject) => {const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();});
};

根底示例

let myFirstPromise = new Promise(function(resolve, reject){// 当异步代码执行胜利时,咱们才会调用 resolve(...), 当异步代码失败时就会调用 reject(...)
    // 在本例中,咱们应用 setTimeout(...) 来模仿异步代码,理论编码时可能是 XHR 申请或是 HTML5 的一些 API 办法.
    setTimeout(function(){resolve("胜利!"); // 代码失常执行!}, 250);
});

myFirstPromise.then(function(successMessage){//successMessage 的值是下面调用 resolve(...) 办法传入的值.
    //successMessage 参数不肯定非要是字符串类型,这里只是举个例子
    console.log("Yay!" + successMessage);
});

Promise.all 的根底应用

Promise.all() 办法接管一个 promise 的 iterable 类型(注:Array,Map,Set 都属于 ES6 的 iterable 类型)的输出,并且只返回一个 Promise 实例,那个输出的所有 promise 的 resolve 回调的后果是一个数组。这个 Promise 的 resolve 回调执行是在所有输出的 promise 的 resolve 回调都完结,或者输出的 iterable 里没有 promise 了的时候。它的 reject 回调执行是,只有任何一个输出的 promise 的 reject 回调执行或者输出不非法的 promise 就会立刻抛出谬误,并且 reject 的是第一个抛出的错误信息。

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {console.log(values);
});
// expected output: Array [3, 42, "foo"]

输入:

> Array [3, 42, "foo"]

Promise 日常应用

日常开发状况下咱们会常常跟 Promise 打交道,上面列举日常应用形式,

先定义一个 Promise 办法,

api.js

function getData(){
    
    return new Promise(resolve => {axios.get('xxxx').then(res => {resolve(res.data)
        })
    }
}

而后在组件外面调用分成两种形式接管:1、async await,2、then,看集体爱好应用哪种形式。

async await 形式

async function query(){
    // res 接管
    let res = await api.getData();}

then 形式

function query(){api.getData().then(res=>{// res 接管});
}

Promise.all 简单应用

上面举个四级联动的例子介绍 Promise.all 的用法,能够跟 Array.map 办法联合应用,如下所示,数组中蕴含选中值:one,two,three 和 four,以及选中值对应的列表:oneList,twoList,threeList 和 fourList,并且四组数据之间存在关联关系。

let arry = [{
    one: '',
    oneList: [],
    two: '',
    twoList: [],
    three: '',
    threeList: [],
    four: '',
    fourList: []},{
    one: '',
    oneList: [],
    two: '',
    twoList: [],
    three: '',
    threeList: [],
    four: '',
    fourList: []},{
    one: '',
    oneList: [],
    two: '',
    twoList: [],
    three: '',
    threeList: [],
    four: '',
    fourList: []}]
// 获取所有 oneList 数据
Promise.all(arr.map(item => this.getOneList()))
   .then(promiseData => {
       // 按程序输入 id 对应的 oneList 数据
       arr.forEach((item,index) => {item.oneList = promiseData[index]
       })
   })
// 获取所有 twoList 数据
Promise.all(arr.map(item => this.getTwoList(item.one)))
   .then(promiseData => {
       // 按程序输入 id 对应的 twoList 数据
       arr.forEach((item,index) => {item.twoList = promiseData[index]
       })
   })
// 获取所有 threeList 数据
Promise.all(arr.map(item => this.getThreeList(item.two)))
   .then(promiseData => {
       // 按程序输入 id 对应的 threeList 数据
       arr.forEach((item,index) => {item.threeList = promiseData[index]
       })
   })
// 获取所有 fourList 数据
Promise.all(arr.map(item => this.getFourList(item.three)))
   .then(promiseData => {
       // 按程序输入 id 对应的 fourList 数据
       arr.forEach((item,index) => {item.fourList = promiseData[index]
       })
   })

这样就能批量获取四级列表数据并赋值到 arry 数组下面,一开始我的解决思路并不是这样,而是在 forEach 外面应用 Promise,发现基本行不通,因为 forEach 自身就是异步的,所以还没等后果返回就曾经执行了。

谬误应用形式

arry.forEach((item, index) => {item.oneList = this.getOneList();
    item.twoList = this.getTwoList(item.one);
    item.threeList = this.getThreeList(item.one);
    item.fourList = this.getFourList(item.one);
})

尽管很简略,然而实际上行不通,肯定要留神。

总结:

1、forEach 不反对 Promise

援用

JavaScript ES6 promise for loop duplicate
How to return many Promises and wait for them all before doing other stuff
Promise.all 联合 async/await
了解和应用 Promise.all 和 Promise.race
JAVASCRIPT 中 FOREACH 的异步问题

退出移动版