前言

我还记得我刚开始学习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();

参考:

  • MDN Promise
  • MDN async
  • MDN for await...of
  • JavaScript权威指南
  • 阮一峰ES6入门之promise

总结

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

JavaScript中Promise的使用方法实例的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  4. Swift与Js通过WebView交互

    开发环境:Swfit2.3XCode8.2基础概念jscontext,jscontext是代表JS的执行环境,通过-evaluateScript:方法就可以执行一JS代码JSValue,JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等JSExport,JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用Swif

  5. JSCore swift

    如果双方相互引用,会造成循环引用,而导致内存泄露。以上是Jscore的基本使用,比较简单

  6. Swift WKWebView的js调用swift

    最近项目需求,需要用到JavaScriptCore和WebKit,但是网上的资源有限,而且比较杂,都是一个博客复制另外一个博客,都没有去实际敲代码验证,下面给大家分享一下我的学习过程。

  7. Swift WKWebView的swift调用js

    不多说,直接上代码:在html里面要添加的的代码,显示swift传过去的参数:这样就实现了swift给js传参数和调用!

  8. 在 Swift 專案中使用 Javascript:編寫一個將 Markdown 轉為 HTML 的編輯器

    你有強烈的好奇心,希望在你的iOS專案中使用JavaScript。jscontext中的所有值都是JSValue對象,JSValue類用於表示任意類型的JavaScript值。因此,我們既需要寫Swift代碼也要寫JavaScript代碼。此外,我們還會在JavaScript中按照這個類的定義來創建一個對象并對其屬性進行賦值。從Swift中呼叫JavaScript就如介紹中所言,JavaScriptCore中最主要的角色就是jscontext類。一個jscontext對象是位於JavaScript環境和本

  9. swift - WKWebView JS 交互

    本文介绍WKWebView怎么与js交互,至于怎么用WKWebView这里就不介绍了HTML代码APP调JS代码结果JS给APP传参数首先注册你需要监听的js方法名2.继承WKScriptMessageHandler并重写userContentController方法,在该方法里接收JS传来的参数3.结果

  10. swift 开发UIWebView跟JS的交互

    前言作为小白的我,才开始入门IOS,选择了swift来进行入门学习,学习做着公司一个简单的小小项目,该项目需要进行跟H5进行交互,然后我就开始研究了UIWebView的使用,其实基本原理跟Android的一样,因为我是Android开发的,所以就顺水推舟了。))//这里设置你需要加载的地址}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()//disposeofanyresourcesthatcanberecreate

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部