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的使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2022-05-11

JS中Promise函数then的奥秘探究

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

浅谈js promise看这篇足够了

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

JavaScript Promise 用法

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

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

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

举例详解JavaScript中Promise的使用

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

JavaScript中的Promise使用详解

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

理解JavaScript中Promise的使用

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

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

ES6中异步对象Promise用法详解

本文实例讲述了ES6中异步对象Promise用法.分享给大家供大家参考,具体如下: 回忆一下ES5中的怎么使用异步方法 // es5中的异步回调 let ajax = function(callback){ console.log('执行') // 执行 setTimeout(() => { callback&&callback.call(); }, 1000) }; ajax(function(){ console.log('hello') // 1s后打印hello }); 使用

JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】

本文实例讲述了JavaScript 函数用法.分享给大家供大家参考,具体如下: 初始函数 Function类型,即函数的类型. 典型的JavaScript函数定义: function 函数名称(参数表){ //函数执行部分 return ; } //注意:参数列表直接写形参名即可 return语句:return返回函数的返回值并结束函数运行 函数也可以看做数据来进行传递 参数列表相当于函数入口,return 语句相当于函数出口 函数可以作为参数来传递. function test ( a ) {

javascript replace()用法详解附实例代码

replace()最简单的算是能力就是简单的字符替换.示例代码如下: var strM = "javascript is a good script language"; //在此我想将字母a替换成字母A alert(strM.replace("a","A")); [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 我想大家运行后可以看到结果,它只替换了首字母.但如果加上正则表达式结果就不一样了!呵呵,没错.replace()支持正则表达

ES6关于Promise的用法详解

Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发. 当然,这并不代表迸发成了全栈.全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交互,后台熟悉数据库的增删查改. 想必接触过Node的人都知道,Node是以异步(Async)回调著称的,其异步性提高了程序的执行效率,但同时也减少了程序的可读性.如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行,这样按照Node的一般执行规律,要实现有序的异步操作,通常是一层加

JavaScript中SetInterval与setTimeout的用法详解

setTimeout 描述 setTimeout(code,millisec) setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. 注:调用过程中,可以使用clearTimeout(id_of_settimeout)终止 参数 描述 code 必需,要调用的函数后要执行的 JavaScript 代码串. millisec 必需,在执行代码前需等待的毫秒数. setTimeinterval setInterval(code,millisec[,"lang"]) 参数

JavaScript中eval()函数用法详解

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行. 如果参数是一个表达式,eval() 函数将执行表达式.如果参数是Javascript语句,eval()将执行 Javascript 语句. 语法 复制代码 代码如下: eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句. eval()函数用法详解: 此函数可能使用的频率并不是太高,但是在某些情况下具有很大的作用,下面就介绍一下eva

JavaScript中的普通函数和箭头函数的区别和用法详解

最近被问到了一个问题: javaScript 中的箭头函数 ( => ) 和普通函数 ( function ) 有什么区别? 我当时想的就是:这个问题很简单啊~(flag),然后做出了错误的回答-- 箭头函数中的 this 和调用时的上下文无关,而是取决于定义时的上下文 这并不是很正确的答案--虽然也不是完全错误 箭头函数中的 this 首先说我的回答中没有错误的部分:箭头函数中的 this 确实和调用时的上下文无关 function make () { return ()=>{ consol

JavaScript中的splice方法用法详解

JavaScript中的splice主要用来对js中的数组进行操作,包括删除,添加,替换等. 注意:这种方法会改变原始数组!. 1.删除-用于删除元素,两个参数,第一个参数(要删除第一项的位置),第二个参数(要删除的项数) 2.插入-向数组指定位置插入任意项元素.三个参数,第一个参数(插入位置),第二个参数(0),第三个参数(插入的项) 3.替换-向数组指定位置插入任意项元素,同时删除任意数量的项,三个参数.第一个参数(起始位置),第二个参数(删除的项数),第三个参数(插入任意数量的项) 示例:

JavaScript对象字面量和构造函数原理与用法详解

本文实例讲述了JavaScript对象字面量和构造函数.分享给大家供大家参考,具体如下: 对象中只有两种属性:(一种比较细的分法) 属性(数据属性)比如:名字,年龄,性别,出版社,地址等信息: 方法(封装代码的属性:函数 ,在这也是一种属性). 在JS中对象的字面量和构造函数是非常的重点,其实在其他的语言中,是没有对象字面量的. 一.对象的字面量的语法: { 属性名: 属性值, 属性名: 属性值, 方法名: 你们函数 } 这个大括号括起来的整个代码块就是叫做对象. var p1 = { } ①访