JavaScript中Promise的使用方法实例

目录
  • 前言
  • Promise简介
  • 什么是回调地狱?
  • Promise的特点
  • 创建Promise实例
  • then方法
    • resolve 和 reject 的参数传递
    • then()链式调用
    • then()的返回值
  • catch方法
  • finally方法
  • Promise的方法
    • Promise.resolve()
    • Promise.reject()
    • Promise.all()
    • Promise.allSettled()
    • Promise.race()
  • async 和 await
    • async函数函数
    • await
    • 异步函数的错误处理
    • 异步函数同样适用于Promise的一些静态方法
    • for await...of
  • 总结

前言

我还记得我刚开始学习JavaScript的Promise很多概念都不懂很"懵逼", 现在已经工作有小半年时间了, 整理整理笔记和个人在工作中的使用情况, 写个文章记录一下(PS只记录怎么使用, 原理太深奥功力不够), 如果有不对的地方前辈勿喷

Promise简介

Promise也称期约, 是ES6推出的一个异步解决方案, 可以有效的解决异步函数嵌套太深("回调地狱")的问题

什么是回调地狱?

假设有个需求需要获取用户的指定数据用户数据3这个数据依赖用户数据2用户数据2又依赖于用户数据1, 所以正确的数据获取数据顺序为: 用户数据1-->用户数据2-->用户数据3, 模拟一下使用回调函数的写法如下:

Node接口:

const router = require('express').Router();

const data1 = { data: "用户数据1" };
router.get('/testData1', (req, res) => {
    res.json(data1);
})

const data2 = { data: "用户数据1,用户数据2" };
router.get('/testData2', (req, res) => {
    if (req.query.data === data1.data) {
        res.json(data2);
    } else {
        res.status(401).json("参数错误");
    }
})

router.get('/testData3', (req, res) => {
    if (req.query.data === data2.data) {
        res.json({ data: "用户数据1,用户数据2,用户数据3" });
    } else {
        res.status(401).json("参数错误");
    }
})

module.exports = router;

前端请求代码:

// 简单封装的 XMLHttpRequest 请求函数
const baseUrl = "http://localhost:8888/test";
const request = (url, cb) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', baseUrl + url);
  xhr.send();
  xhr.onreadystatechange = () => {
    const { readyState, status, response } = xhr;
    if (readyState === 4) {
      if (status >= 200 && status <= 299) {
        cb(JSON.parse(response));
      } else {
        throw new Error(response);
      }
    }
  }
}

// 因为下一个请求需要上一个请求的数据所以需要一个回调函数嵌套一个回调函数
request("/testData1", res1 => {
  console.log(res1); // => {data: '用户数据1'}
  request(`/testData2?data=${res1.data}`, res2 => {
    console.log(res2); // => {data: '用户数据1,用户数据2'}
    request(`/testData3?data=${res2.data}`, res3 => {
      console.log("需求需要的数据", res3); // => 需求需要的数据 {data: '用户数据1,用户数据2,用户数据3'}
      // ....
    })
  })
})

这个代码看着就头大, 如果需求复杂的话, 我只能用一张图表示(这张图片我也不记得从哪里保存的忘了)

这种一个回调嵌套一个回调的代码可读性和可维护性都很差, 被称为"回调地狱", 而Promise的出现就可以很好的解决这个问题

Promise的特点

Promise对象有一个状态, 这个状态不受外界影响, 状态一共分为3种:

  • Pending状态 (进行中(又称待定)) 初始状态
  • Fulfilled状态 (成功(又称兑现))
  • Rejected状态(失败(又称拒绝))

关于Promise的状态叫法下文统一使用成功,失败

一旦Promise对象的状态改变(成功或失败)就不会再变, 是单向的:

Pending(进行中) -> Fulfilled(成功)

Pending(进行中) -> Rejected(失败)

创建Promise实例

创建Promise实例需要newPromise构造函数, 该构造函数接受一个函数(处理器函数)作为参数, 该函数会收到两个参数, 这两个参数分别是resolve和reject(叫什么都行一般还是要语义化名称)它们是两个函数, 不用自己实现就可以使用, 如下:

const p = new Promise((resolve, reject) => {

})
console.log(p);

可以看到这个状态默认是Pending(进行中)

resolve和reject这两个参数(函数)可以在处理器函数里面调用(可以传递参数), 这样将会改变 Promise 对象的状态:

const p = new Promise((resolve, reject) => {
  resolve();
})
console.log(p);

当调用resolve函数时会将Priomise对象的状态修改为Fulfilled(成功), 调用reject函数则会将状态修改为Rejected(失败)

then方法

Promise实例的then方法, 可以接受两个参数(都是函数)分别指定Primise实例里面状态(成功或失败)改变时调用的回调函数(并且Promise的then方法是异步的微任务):

const p = new Promise((resolve, reject) => {
  // 将p的状态修改为成功
  resolve();
})

console.log("同步代码");
p.then(
  () => {
    console.log("成功的回调");
  },
  () => {
    console.log("失败的回调");
  }
)

结果如下:

反之调用reject函数就会触发then方法的第二个回调函数, 如果将resolve函数和reject函数都调用只会生效最先调用的(因为状态时单向的嘛)

resolve 和 reject 的参数传递

经过上面的测试我们知道resolve和reject这两个函数是可以修改状态并且触发Promise的then方法的回调函数的, 那么是函数就可以传递参数, 这个参数会被传递给对应的then方法的回调函数接收到:

const p = new Promise((resolve, reject) => {
  // 将p的状态修改为成功, 并且传递一个参数
  resolve("ok");
})

console.log("同步代码");
p.then(
  // 这里接收 resolve 函数传递的参数
  res => {
    console.log("成功的回调", res);
  },
  // 这里接收 reject 函数传递的参数
  err => {
    console.log("失败的回调");
  }
)

结果如下:

then()链式调用

了解完then方法以后我们就可以稍微修改一下一开始最上面的需求:

// 请求函数使用 Promise 封装
const baseUrl = "http://localhost:8888/test";
const request = (url) => {
  // 返回一个Promise实例
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', baseUrl + url);
    xhr.send();
    xhr.onreadystatechange = () => {
      const { readyState, status, response } = xhr;
      if (readyState === 4) {
        if (status >= 200 && status <= 299) {
          const res = JSON.parse(response);
          // 修改状态为成功并且把响应传递过去
          resolve(res);
        } else {
          // 修改状态为失败也把响应传递过去
          reject(response);
        }
      }
    }
  })
}

// 使用then方法
request("/testData1").then(
  res1 => {
    console.log(res1); // {data: '用户数据1'}
    request(`/testData2?data=${res1.data}`).then(
      res2 => {
        console.log(res2); // {data: '用户数据1,用户数据2'}
        request(`/testData3?data=${res2.data}`).then(
          res3 => {
            console.log("需求需要的数据", res3); // => 需求需要的数据 {data: '用户数据1,用户数据2,用户数据3'}
          }
        )
      }
    )
  }
)

写完以后发现好像还不如使用回调函数的方式写, 看到这里好像Promise还是不能很好的解决回调嵌套的问题; 换个思路如果我们在then方法中再返回一个Promise实例, 那么不就又可以调用then方法了吗? 代码中测试一下:

const p1 = new Promise((resolve, reject) => {
  resolve("p1数据");
})

// 这里的p2就是p1.then方法成功回调里面返回的p2
const p2 = p1.then(
    // 这里的res1参数就是p1的处理器函数中调用 resolve("p1数据") 传递的参数
    res1 => {
      console.log(res1); // p1数据

      // 这里新建一个新的Promise实例, 记作p2
      const p2 = new Promise((resolve, reject) => {
        // 0.5s后修改状态
        setTimeout(() => {
          resolve(res1 + ",p2数据");
        }, 500);

      })
      // 将p2返回
      return p2;
    }
  )

const p3 = p2.then(
  res2 => {
    console.log(res2); // p1数据,p2数据
    // 这里和上面的同理
    const p3 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(res2 + ",p3数据");
      }, 500);

    })
    return p3;
  }
)

p3.then(
  res3 => {
    console.log(res3); // p1数据,p2数据,p3数据
  }
)

发现可行后, 把需求代码再修改一下:

// 这里的p1就是 request("/testData1") 返回的Promise实例
const p1 = request("/testData1");

// 这里的p2就是p1.then方法成功回调返回的p2
const p2 = p1.then(
    res1 => {
      console.log(res1); // {data: '用户数据1'}

      // 再调用request方法将其返回的Promise实例记作p2
      const p2 = request(`/testData2?data=${res1.data}`);
      // 将p2返回
      return p2;
    }
  )

const p3 = p2.then(
  res2 => {
    console.log(res2); // {data: '用户数据1,用户数据2'}
    // 这里和上面的同理
    const p3 = request(`/testData3?data=${res2.data}`);
    return p3;
  }
)

p3.then(
  res3 => {
    console.log("需求需要的数据", res3); // 需求需要的数据 {data: '用户数据1,用户数据2,用户数据3'}
  }
)

需求实现是实现了, 就是代码有点冗余, 可以精简一下, 如下:

request("/testData1").then(
  res1 => {
    console.log(res1); // {data: '用户数据1'}
    // 这里直接返回 request方法的返回值Promise实例
    return request(`/testData2?data=${res1.data}`);
  }
).then(
  // 这个成功回调时上一个then方法返回的Promise实例的成功回调
  res2 => {
    console.log(res2); // {data: '用户数据1,用户数据2'}
    // 同理
    return request(`/testData3?data=${res2.data}`);
  }
).then(
  // 同理
  res3 => {
    console.log("需求需要的数据", res3); // 需求需要的数据 {data: '用户数据1,用户数据2,用户数据3'}
  }
)

上面的代码格式就像链条一样所以又被称为"链式调用"

then()的返回值

经过上面的代码测试, then方法除了返回Promise对象外还可以返回其他任意的值, 返回会被转换为Promise对象, 内部的状态视返回值而定:

const p1 = new Promise(resolve => resolve());
p1.then(() => {
  // 这里相当于是 return undefined
}).then(
  res1 => {
    console.log(res1); // undefined
    return "hello";
  }
).then(
  res2 => {
    console.log(res2); // hello
    return { name: "张三" };
  }
).then(
  res3 => {
    console.log(res3); // { name: "张三" }

    // 返回错误对象该Promise对象的状态也是成功
    return new Error("error object");
  }
).then(
  res4 => {
    console.log(res4 instanceof Error); // true
    console.log(res4.message); // error object

    // 抛出一个错误则该Promise对象的状态是失败
    throw "thorw error";
  }
).then(
  () => { },
  err => {
    console.log(err); // thorw error
  }
)

catch方法

上面使用then方法的链式调用可以解决回调嵌套太深的问题, 但是还没处理请求之间的失败回调处理, then方法的第二个回调就是指定失败的回调, 但是一般都不使用这个回调来处理错误, 而是使用catch方法来失败, 使用格式如下:

p1.then(
  // ...
).then(
  // ...

).catch(err => { // 这个catch可以捕获这一条调用链上的错误
    // 处理错误
})

finally方法

除了catch方法那自然就有finally方法, finally方法和try...catch...finally中的finally是一样的作用, 使用格式如下:

p.then(
  // ...
).then(
  // ...

).catch(err => { // 这个catch方法可以捕获这一条调用链上的错误
  // 处理错误

}).finally(() => { // 无论成功还是失败这个finally中指定的回调都会执行
  // 清除loading, 重置状态...
})

Promise的方法

Promise.resolve()

立即返回一个状态是成功(Fulfilled) 的 Promise 对象, 可以传递参数, 参数会被其返回的Promise实例的then方法的回调(异步微任务)接受到:

const p = Promise.resolve("Promise.resolve");
p.then(res => console.log(res)); // Promise.resolve

也可以利用Promise.resolve()来创建一个微任务:

console.log("同步代码");

setTimeout(() => console.log("setTimeout"), 0);

const p = Promise.resolve("Promise.resolve");
p.then(res => console.log(res));

结果如下:

Promise.reject()

Promise.resolve()一样不过返回的状态是失败(Rejected) 的Promise对象(同样是微任务)

console.log("同步代码");

setTimeout(() => console.log("setTimeout"), 0);

const p = Promise.reject("Promise.reject");
p.then().catch(err => console.log("Promise.reject"));

Promise.all()

Promise.all接收一个Promise的iterable类型(就是可迭代对象里面存放着Promise实例, Array, Map, Set都属于ES6的iterable类型), Promise.all 会等待所有的Promise对象都完成(或第一个失败) , 根据给定的参数返回不同的参数

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p2 data"), 1000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p3 data"), 1500);
})

// 依次打印数据
p1.then(res => console.log(res)); // 0.5s 后打印 p1 data
p2.then(res => console.log(res)); // 1.0s 后打印 p2 data
p3.then(res => console.log(res)); // 1.5s 后打印 p3 data

const proArray = [p1, p2, p3];
Promise.all(proArray).then(resList => {
  console.log(resList); // 1.5s后打印数据 ['p1 data', 'p2 data', 'p3 data']
}).catch(err => {
  // 如果在`Promise.all`方法中出现了失败的状态, 那么这个参数会是这个失败状态返回的参数(如果有的话)
  console.error("error: ", err);
})

利用Promise.all()方法的特定可以用于同时发送多个请求, 如下例子:

Node接口:

const getRandom = () => Math.random() * 9 + 1;
router.get('/testData4', (req, res) => {
    let n = req.query.n;
    const random = getRandom();

    // 定时器模拟接口响应时间差
    setTimeout(() => {
        res.json(`第${++n}个请求${random}`);
    }, random * 50);
});

前端发送多个请求:

const proArray = [];
for (let i = 0; i < 10; i++) {
  // 将10个请求方法返回的Promsie对象添加到proArray数组中
  proArray.push(request(`/testData4?n=${i}`));
}
Promise.all(proArray).then(resList => {
  for (const res of resList) {
    // 每个请求的返回结果
    console.log(res);
  }
})

Promise.allSettled()

Promise.allSettled()方法和Promise.all()很类似只不过是接受的期约对象无论是成功还是失败都会触发then方法的成功回调, 每个期约都会返回一个对象status属性表示状态, value表示成功回调的值, 如果状态是失败的那么失败回调的值存储在reason属性中:

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);;
})
const p2 = new Promise((resolve, reject) => {
  // p2的Promise实例的状态修改为失败
  setTimeout(() => reject("p2 err"), 1000);
})

const proArray = [p1, p2];
Promise.allSettled(proArray).then(resList => {
  console.log(resList); // (2) [{…}, {…}]

  for (const res of resList) {
    const { status, value, reason } = res;
    if (reason) {
      console.log(`失败: ${status}, 原因是: ${reason}`); // 失败: rejected, 原因是: p2 err
    } else {
      console.log(`成功: ${status}, 数据是: ${value}`); // 成功: fulfilled, 数据是: p1 data
    }
  }
}).catch(err => {
  // 这里不会捕获p2的失败的回调
  console.error("error: ", err);
})

Promise.race()

Promise.race()Promise.all()类似, 都接收一个可以迭代的参数, 但是不同之处是

Promise.race()的状态变化不是受全部参数的状态影响, 一旦迭代器中的某个Promise解决或拒绝,返回的 Promise就会解决或拒绝

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => resolve("p1 data"), 500);;
})
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => reject("p2 err"), 1000);
})

const proArray = [p1, p2];
Promise.race(proArray).then(res => {
    console.log(res); // p1 data
}).catch(err => {
    console.error(err);
})

async 和 await

async函数函数

async函数函数就是使用async关键字声明的函数(也叫异步函数), async函数和普通的函数使用没有什么区别:

// 函数声明
async function asyncFn1() {
  console.log("asyncFn1");
}

// 函数表达式
const asyncFn2 = async () => {
  console.log("asyncFn2");
}

asyncFn1();
asyncFn2();

// 立即调用
(async () => {
  console.log("asyncFn3");
})();

await

await操作符用于等待一个Promise对象, 它只能在async function中使用, 使用async+await可以将异步的代码"变"的跟同步的一样:

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("data");
  }, 1000);
});

// async 函数
async function asyncFn() {
  console.log("asyncFn函数开始执行");

  // await 会等待右边的Promise对象的状态变成功后返回其值
  const res = await p;
  console.log(res); // data

  console.log("asyncFn函数执行完了");
}

// 调用
asyncFn();

上面的代码会先输出"asyncFn函数开始执行"后, 等待1s左右输出"data", 然后再输出"asyncFn函数执行完了"

注意: 异步函数不会阻塞主线程的执行, 它是异步的:

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("data");
  }, 1000);
});

// async 函数
async function asyncFn() {
  console.log("asyncFn函数开始执行");
  const res = await p;
  console.log(res);
  console.log("asyncFn函数执行完了");
}

console.log("hello");
asyncFn();
console.log("javascript");

等待大约1s后上面的代码执行结果如下:

根据上面的代码执行结果, 我们发现异步函数内await关键字会等待其右边的Promise对象的返回值, 等待结束后, 后面的代码才会被执行, 利用这个特性我们可以在JavaScript中可以实现类似Java的Thread.sleep()方法, 如下:

const sleep = async time => new Promise(resolve => setTimeout(resolve, time));

(async () => {
  console.log("1");
  await sleep(1000);
  console.log("2");
  await sleep(500);
  console.log("2.5");
})();

了解完async和await的使用后我们可以使用异步函数再来完成我们一开始的需求:

// 请求函数使用 Promise 封装
const baseUrl = "http://localhost:8888/test";
const request = (url) => {
  // 返回一个Promise实例
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', baseUrl + url);
    xhr.send();
    xhr.onreadystatechange = () => {
      const { readyState, status, response } = xhr;
      if (readyState === 4) {
        if (status >= 200 && status <= 299) {
          const res = JSON.parse(response);
          // 修改状态为成功并且把响应传递过去
          resolve(res);
        } else {
          // 修改状态为失败也把响应传递过去
          reject(response);
        }
      }
    }
  })
}

async function asyncFn() {
  const res1 = await request("/testData1");
  console.log(res1); // {data: '用户数据1'}

  const res2 = await request(`/testData2?data=${res1.data}`);
  console.log(res2); // {data: '用户数据1,用户数据2'}

  const res3 = await request(`/testData3?data=${res2.data}`);
  console.log(res3); // {data: '用户数据1,用户数据2,用户数据3'}
}

asyncFn();

可以看到使用async和await来发送网络请求写的代码很简洁, 也很直观

异步函数的错误处理

异步函数的异常处理可以使用try...catch和catch处理:

try...catch

async function asyncFn() {
  let res1, res2, res3;
  try {
    res1 = await request("/testData1");

    try {
      if (res1?.data) {
        res2 = await request(`/testData2?data=${res1.data}`);
      }

      try {
        if (res2?.data) {
          res3 = await request(`/testData3?data=${res2.data}`);
        }

      } catch (error) {
        // 处理res3 error
      }

    } catch (error) {
      // 处理res2 error
    }

  } catch (error) {
    // 处理res3 error
  }
}

catch

async function asyncFn() {
  const res1 = await request("/testData1")
    .catch(err => {
      // 处理res1 error
    });

  if (res1?.data) {
    const res2 = await request(`/testData2?data=${res1.data}`)
      .catch(err => {
        // 处理res2 error
      });

    if (res2?.data) {
      const res3 = await request(`/testData3?data=${res2.data}`)
        .catch(err => {
          // 处理res3 error
        });
    }
  }
}

异步函数同样适用于Promise的一些静态方法

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p2 data"), 1000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p3 data"), 1500);
})

const proArray = [p1, p2, p3];
async function asyncFn() {
  const list = await Promise.all(proArray);
  console.log(list); // ['p1 data', 'p2 data', 'p3 data']
}
asyncFn();

for await...of

一个数组中存储多个Promise对象我们可以通过Promise.all获取或者通过循环来等待其返回值, 我们使用循环:

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1 data"), 500);
})
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p2 data"), 1000);
})
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p3 data"), 1500);
})

const proArray = [p1, p2, p3];

async function asyncFn() {
  for (const pro of proArray) {
    // 这里不要忘记 await
    const res = await pro;
    console.log(res);
  }
}
asyncFn();

ES9开始有一个新语法就是for await..of可以自动等待每次循环的项

async function asyncFn() {
  for await (const item of proArray) {
    console.log(item);
  }
}
asyncFn();

参考:

总结

到此这篇关于JavaScript中Promise使用的文章就介绍到这了,更多相关JS Promise的使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Javascript Promise用法详解

    1.约定 本文的 demo 代码有些是伪代码,不可以直接执行. 没有特殊说明,本文所有 demo 都是基于 ES6 规范. Object.method 代表是静态方法, Object#method 代表的是实例方法.如 Promise#then 代表的是 Promise 的实例方法, Promise.resolve 代表的是 Promise 的静态方法. 2.什么是 Promise? 首先我们来了解 Promise 到底是怎么一回事 Promise 是抽象的异步处理对象,以及对其进行各种操作的组

  • Javascript中Promise的四种常用方法总结

    前言 Promise是JavaScript异步操作解决方案,最近看到项目里不少人用了Promise 的库类,比如 bluebird.q .jQuery.Deffered 等 polyfill promise 方式,使用的时候翻看长长的文档,真心累觉不爱. es5 发展到现在,node 在0.12版本就已经支持了promise, 在客户端,大部分浏览器也支持了Promise, 如果要兼容低版本的浏览器,可以加上es5-shim等 polyfill promise.下面话不多说,来一起看看详细的介绍

  • 详细解读JavaScript编程中的Promise使用

    Promise核心说明 尽管Promise已经有自己的规范,但目前的各类Promise库,在Promise的实现细节上是有差异的,部分API甚至在意义上完全不同.但Promise的核心内容,是相通的,它就是then方法.在相关术语中,promise指的就是一个有then方法,且该方法能触发特定行为的对象或函数. Promise可以有不同的实现方式,因此Promise核心说明并不会讨论任何具体的实现代码. 先阅读Promise核心说明的意思是:看,这就是需要写出来的结果,请参照这个结果想一想怎么用

  • JavaScript中的Promise使用详解

    许多的语言,为了将异步模式处理得更像平常的顺序,都包含一种有趣的方案库,它们被称之为promises,deferreds,或者futures.JavaScript的promises ,可以促进关注点分离,以代替紧密耦合的接口. 本文讲的是基于Promises/A 标准的JavaScript promises.[http://wiki.commonjs.org/wiki/Promises/A] Promise的用例: 执行规则 多个远程验证 超时处理 远程数据请求 动画 将事件逻辑从应用逻辑中解耦

  • 浅谈js promise看这篇足够了

    一.背景 大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着.但是也有一个不好的地方,当我们有很多回调的时候,比如这个回调执行完需要去执行下个回调,然后接着再执行下个回调,这样就会造成层层嵌套,代码不清晰,很容易进入"回调监狱",就容易造成下边的例子: async(1, function(value){ async(value, function(value){ async(value, fu

  • 举例详解JavaScript中Promise的使用

    摘录 – Parse JavaScript SDK现在提供了支持大多数异步方法的兼容jquery的Promises模式,那么这意味着什么呢,读完下文你就了解了. "Promises" 代表着在javascript程序里下一个伟大的范式,但是理解他们为什么如此伟大不是件简单的事.它的核心就是一个promise代表一个任务结果,这个任务有可能完成有可能没完成.Promise模式唯一需要的一个接口是调用then方法,它可以用来注册当promise完成或者失败时调用的回调函数,这在Common

  • 理解JavaScript中Promise的使用

    Javascript 采用回调函数(callback)来处理异步编程.从同步编程到异步回调编程有一个适应的过程,但是如果出现多层回调嵌套,也就是我们常说的厄运的回调金字塔(Pyramid of Doom),绝对是一种糟糕的编程体验.于是便有了 CommonJS 的 Promises/A 规范,用于解决回调金字塔问题.本文先介绍 Promises 相关规范,然后再通过解读一个迷你的 Promises 以加深理解. 什么是 Promise 一个 Promise 对象代表一个目前还不可用,但是在未来的

  • JS中Promise函数then的奥秘探究

    Promise概述 Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口. 那么,什么是Promises? 首先,它是一个对象,也就是说与其他JavaScript对象的用法,没有什么两样:其次,它起到代理作用(proxy),充当异步操作与回调函数之间的中介.它使得异步操作具备同步操作的接口,使得程序具备正常的同步运行的流程,回调函数不必再一层层嵌套. 简单说,它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立刻返回,所以可以采用同步操作的流程.这

  • JavaScript Promise 用法

    同步编程通常来说易于调试和维护,然而,异步编程通常能获得更好的性能和更大的灵活性.异步的最大特点是无需等待."Promises"渐渐成为JavaScript里最重要的一部分,大量的新API都开始promise原理实现.下面让我们看一下什么是promise,以及它的API和用法! Promises现状 XMLHttpRequest API是异步的,但它没有使用promise API.但有很多原生的 javascript API 使用了promise: *Battery API *fetc

  • JavaScript中Promise的使用方法实例

    目录 前言 Promise简介 什么是回调地狱? Promise的特点 创建Promise实例 then方法 resolve 和 reject 的参数传递 then()链式调用 then()的返回值 catch方法 finally方法 Promise的方法 Promise.resolve() Promise.reject() Promise.all() Promise.allSettled() Promise.race() async 和 await async函数函数 await 异步函数的错

  • ES6中Promise的使用方法实例总结

    本文实例讲述了ES6中Promise的使用方法.分享给大家供大家参考,具体如下: 在javascript中,代码是单线程执行的,对于一些比较耗时的IO操作,都是通过异步回调函数来实现的. 但是这样会存在一个问题,当下一个的操作需要上一个操作的结果时,我们只能把代码嵌到上一个操作的回调函数里,这样一层嵌一层,最终形成回调地狱. $.get('/login.php', function (login) { $.get('/user.php', function (user) { $.get('/in

  • JavaScript中扩展Array contains方法实例

    javascript的Array没有contains方法,有时候这会不方便,contains方法实现很简单: 复制代码 代码如下: function contains(a, obj) {     var i = a.length;     while (i--) {        if (a[i] === obj) {            return true;        }     }     return false; } 当然我们也可以扩展Array类,如下js 复制代码 代码如下

  • JavaScript中call和apply方法的区别实例分析

    本文实例分析了JavaScript中call和apply方法的区别.分享给大家供大家参考,具体如下: 这两个方法不经常用,但是在某些特殊场合中是非常有用的,下面主要说下它们的区别: 1.首先,JavaScript是一门面向对象的语言,也就是说它有this的概念.而且JavaScript是一门动态类型语言,为什么说它是动态类型语言呢?因为JavaScript在编译时没有类型检查的过程,不会去检查创建的对象类型,也不会去检查传递的参数类型,所以它的变量类型在运行期间是可以改变的. 2.要知道call

  • JavaScript 中使用 Generator的方法

    Generator 是一种非常强力的语法,但它的使用并不广泛(参见下图 twitter 上的调查!).为什么这样呢?相比于 async/await,它的使用更复杂,调试起来也不太容易(大多数情况又回到了从前),即使我们可以通过非常简单的方式获得类似体验,但是人们一般会更喜欢 async/await. 然而,Generator 允许我们通过 yield 关键字遍历我们自己的代码!这是一种超级强大的语法,实际上,我们可以操纵执行过程!从不太明显的取消操作开始,让我们先从同步操作开始吧. 我为文中提到

  • javascript中Promise使用详解

    目录 一.首先,要知道为什么要用Promise语法? 二.接着,来了解一下回调地狱(Callback Hell) 三.最后,也是本章的重头戏,Promise的基本使用 (一) resolve函数 (二) rejected函数 (三)Promise的API 1. then 2. catch 3. finally 4. Promise.all 5. Promise.race 四.最后 前言: 做过前端开发的都知道,JavaScript是单线程语言,浏览器只分配给JS一个主线程,用来执行任务,但是每次

  • JavaScript中Promise处理异步的并行与串行

    目录 一.异步的“并行” 并行中的综合处理 二.异步的“串行”: 2.1 then链机制处理 2.2 真实项目中,想实现异步的串行,我们一般使用async+await 2.3 promise.then(onfulfilled,onrejected) 在内存中的执行 三.aysnc修饰符 四.await:等待 await中的异步 五.思考题 思考题1 思路及图解 思考题2 思路及图解 思考题3 思路及图解 总结 一.异步的“并行” 同时处理,相互之间没啥依赖 // 执行FN1返回一个promise

  • 模拟javascript中的sort排序(简单实例)

    一.javascript中sort对数据进行排序的原理 sort() 方法对数组的元素做原地的排序,并返回这个数组. sort 可能不是稳定的.默认按照字符串的Unicode码位点排序; 语法:arr.sort([compareFunction]) 参数 compareFunction 可选.用来指定按某种顺序进行排列的函数.如果省略,元素按照转换为的字符串的诸个字符的Unicode位点进行排序. 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前: 如

  • 深入理解关于javascript中apply()和call()方法的区别

    如果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而怪异的感觉,因为意识上往往不可能的事偏偏就发生了,甚至觉得不可理喻.如果在学JavaScript这自由而变幻无穷的语言过程中遇到这种感觉,那么就从现在形始,请放下的您的"偏见",因为这对您来说绝对是一片新大陆,让JavaScrip慢慢融化以前一套凝固的编程意识,注入新的生机! 好,言归正传,先理解JavaScrtipt动态变换运行时上下文特性,这种特性主要就体现在apply, call两个方法的运用上.

随机推荐