什么是Promise?

英文翻译:承诺!

js里:

Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。

ECMAscript 6 原生提供了 Promise 对象。

Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。

Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。

理解 Promise

Promise 简介:

"假设你是一个宝宝. 你的妈妈承诺(Promise)你,下个礼拜她会给你一台新手机。"

不知道,下个礼拜你是否会拿到手机。你的妈妈可以真的给你买一个全新的手机,或者放你鸽子,也有可能如果她不开心:(了就扣下了手机。

这个就是承诺(Promise)。一个 Promise 有3个状态。他们分别是:

  1. Promise 是待定的(pending): 你不知道你下个礼拜能不能拿到手机。
  2. Promise 是已解决的(resolved):你的妈妈真的给你买了一个全新的手机。
  3. Promise 是被拒绝的(rejected): 因为你妈妈不开心所以不给你手机了。

Promise 对象有以下两个特点:

1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:

  • pending: 初始状态,不是成功或失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。

只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。

2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

Promise 优缺点

有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。

Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

基本用法

语法

new Promise( function(resolve, reject) {...} /* executor */  )
复制代码
  • 构建 Promise 对象时,需要传入一个 executor 函数,主要业务流程都在 executor 函数中执行。
  • Promise构造函数执行时立即调用executor 函数, resolve 和 reject 两个函数作为参数传递给executor,resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。一旦状态改变,就不会再变,任何时候都可以得到这个结果。
  • 在 executor 函数中调用 resolve 函数后,会触发 promise.then 设置的回调函数;而调用 reject 函数后,会触发 promise.catch 设置的回调函数。

值得注意的是,Promise 是用来管理异步编程的,它本身不是异步的,new Promise的时候会立即把executor函数执行,只不过我们一般会在executor函数中处理一个异步操作。

创建一个 Promise

让我们将这个转化为 JavaScript。

/* ES5 */
var isMomHappy = false;
// Promise
var willIGetNewPhone = new Promise(function (resolve, reject) {if (isMomHappy) {var phone = {brand: 'Samsung',color: 'black'};resolve(phone); // 完成了} else {var reason = new Error('妈妈不开心');reject(reason); // reject}}
); 

代码本身颇具表现力。

  1. 我们用一个布尔值 isMomHappy,来定义妈妈是否开心。

  2. 我们有一个命名为willIGetNewPhone的 Promise 。这个 Promise 可以是 已完成的(resolved) (如果妈妈给你买了一个新手机)或者 被拒绝的(rejected)(妈妈不开心,她没有给你买一个)。

  3. 这里有一个标准的语法来新建一个 Promise,参考MDN 文档,一个 promise 语法看上去像这样。

// promise 语法看上去像这样
new Promise(/* executor*/ function (resolve, reject) { ... } );
  1. 你需要记住的是,当结果是正确的,在你的 promise 中调用 resolve(正确的值)。在我们的例子中,如果妈妈很开心,我们就会拿到手机。因此,我们调用 resolve 函数和 phone 这个变量。如果我们的妈妈不开心,我们会调用 reject 函数和一个理由(reason)reject(reason)

使用 Promise

现在,我们有一个 Promise。来看看怎么使用它:

/* ES5 */
...
// 调用我们的 Promise
var askMom = function () {willIGetNewPhone.then(function (fulfilled) {// 太好啦, 你获得了一个新手机console.log(fulfilled);// output: { brand: 'Samsung', color: 'black' }}).catch(function (error) {// 好不幸,你妈妈没买手机console.log(error.message);// output: '妈妈不开心'});
};
askMom();
  1. 我们有一个名为 askMom 的函数。在这个函数中,我们会使用 Promise willIGetNewPhone

  2. 一旦 Promise 被解决(resolved)或者被拒(rejected),我门希望采取些措施。我们用 .then 和 .catch 来实现。

  3. 在我们的例子中,.then 之中有个 function(fulfilled) { ... } 。fulfilled 是什么?fulfilled 就是是你传入 Promise 的 resolve(your_success_value).因此,在我们例子中就是 phone

  4. 我们在 .catch 中有 function(error){ ... }error 是什么?正如你猜测的,error 正是你传入 Promise 中的 reject(your_fail_value) 。因此,在我们的例子中就是 reason

让我们看看例子运行之后的结果吧!

Demo: JS Bin - Collaborative JavaScript Debugging

串联 Promise

Promiss 是可串联的。

也就是说,你,宝宝,承诺(Promise)你的小伙伴,当你妈妈给你买了手机,你就会给他们看新手机。

这就是另一个 Promise 啦。我们来写一个!

// 简略
...
// 第二个 promise
var showOff = function (phone) {return new Promise(function (resolve, reject) {var message = 'hey 伙计,我有个新 ' +phone.color + ' ' + phone.brand + '手机';resolve(message);});
};

说明:

  • 在这个例子中,你可能意识到我们没有调用 reject。因为这个是可选的参数。

  • 我们可以简化这个样例就像用 Promise.resolve 代替。

// 简略
...// 第二个 promise
var showOff = function (phone) {var message = 'hey 伙计,我有个新 ' +phone.color + ' ' + phone.brand + ' 手机';return Promise.resolve(message);
};

说明:

  • 在这个例子中,你可能意识到我们没有调用 reject。因为这个是可选的参数。

  • 我们可以简化这个样例就像用 Promise.resolve 代替。

// 简略
...// 第二个 promise
var showOff = function (phone) {var message = 'hey 伙计,我有个新 ' +phone.color + ' ' + phone.brand + ' 手机';return Promise.resolve(message);
};

让我们串联 Promise。你,宝宝只能在willIGetNewPhone Promise 实现之后,才能开始 showOff Promise。

...
// 调用 Promise
var askMom = function () {willIGetNewPhone.then(showOff) // 在这里串联.then(function (fulfilled) {console.log(fulfilled);// output: 'Hey 伙计, 我有一个新的黑色三星手机。'}).catch(function (error) {// 好不幸,你妈妈没买手机console.log(error.message);// output: '妈妈不开心'});
};

串联 Promise 简单吧!

Promises 是异步的

Promise 是异步的。让我们在调用 Promise 之前和之后各打印一个信息。

// 调用我们的Ppromise
var askMom = function () {console.log('询问妈妈之前'); // 运行之前打印willIGetNewPhone.then(showOff).then(function (fulfilled) {console.log(fulfilled);}).catch(function (error) {console.log(error.message);});console.log('询问妈妈之后'); // 运行之后打印
} 

预计的输出序列是怎么样的?也许你预计是这样的

1\. 询问妈妈之前
2\. Hey 伙计, 我有一个新的黑色三星手机。
3\. 询问妈妈之后

然而, 真实的输出顺序是这样的:

1\. 询问妈妈之前
2\. 询问妈妈之后
3\. Hey 朋友, 我有一个新的黑色三星手机。

为什么? 因为生命 (或者 JavaScript) 不等人。

宝宝在玩的时候等待着妈妈的承诺(promise) (新手机).不是吗? 这个我们称之为 异步(asynchronous), 代码不会因为阻塞或等待结果而不运行. 任何想等待 Promise 之后再运行的, 你需要把他们放入 .then.

ES5, ES6/2015, ES7/Next 中的 promise

ES5 - 大多数浏览器

demo代码在 ES5 的环境(所有主流浏览器+NodeJs)中是可以运行,如果你包含了Bluebird Promise 库。这是因为 ES5 不支持直接调用 Promise 。另一个有名的 Promise 库是 Kris Kowal 的Q。

ES6 / ES2015 - 现代浏览器, NodeJs v6

demo代码可以直接调用,因为ES6支持本地 Promise。外加,和 ES6 函数 fat arrow =>,以及 const 和 let 搭配使用,我们可以进一步简化代码`。

这里是 ES6 代码的例子

/* ES6 */
const isMomHappy = true;// Promise
const willIGetNewPhone = new Promise((resolve, reject) => { // fat arrowif (isMomHappy) {const phone = {brand: 'Samsung',color: 'black'};resolve(phone);} else {const reason = new Error('mom is not happy');reject(reason);}}
);const showOff = function (phone) {const message = 'Hey 伙计, 我有个一个新' +phone.color + ' ' + phone.brand + '手机';return Promise.resolve(message);
};// 调用我们的promise
const askMom = function () {willIGetNewPhone.then(showOff).then(fulfilled => console.log(fulfilled)) // fat arrow.catch(error => console.log(error.message)); // fat arrow
};askMom();

注意,所有的var都用 const代替。所有的 function(resolve, reject) 都简化为(resolve, reject) =>。 这些改变有许多好处。:

  • JavaScript ES6 的变量声明, let 和 const

  • Javascript ES6 箭头函数介绍

ES7 - 异步等待让语法看上去更整洁

ES7 引入 async 和 await 语法。这让异步语法看上去更整洁和易于理解,而不用.then和 .catch

用 ES7 的语法重写例子

/* ES7 */
const isMomHappy = true;// Promise
const willIGetNewPhone = new Promise((resolve, reject) => {if (isMomHappy) {const phone = {brand: 'Samsung',color: 'black'};resolve(phone);} else {const reason = new Error('妈妈不开心');reject(reason);}}
);// 2nd promise
async function showOff(phone) {return new Promise((resolve, reject) => {var message = 'Hey 伙计, 我有一个新' +phone.color + ' ' + phone.brand + '手机';resolve(message);});
};// 调用 Promise
async function askMom() {try {console.log('before asking Mom');let phone = await willIGetNewPhone;let message = await showOff(phone);console.log(message);console.log('after asking mom');}catch (error) {console.log(error.message);}
}(async () => {await askMom();
})();
  1. 每当你需要在函数中返回一个 Promise 的时候,你要在函数之前添加 async。 E.g. async function showOff(phone)

  2. 当你需要调用一个 promise,你需要在此之前添加 await。 E.g. let phone = await willIGetNewPhone; and let message = await showOff(phone);.

  3. 使用 try { ... } catch(error) { ... } 来捕捉 Promise 错误,被拒绝的 promise

为什么用 Promise 以及何时用他们?

为什么你需要 promise ?在 promise 之前我们是如何的?在回答这些问题之前,让我们回到基本原理。

普通函数 vs 异步函数

让我们看看这两个例子,他们都执行两个数字相加,一个用普通函数相加,一个用远程方法相加。

普通函数相加两个数字

// 正常相加数字function add (num1, num2) {return num1 + num2;
}const result = add(1, 2); // you get result = 3 immediately 

异步函数相加两个数字

// 远程相加数字// 调用api获得结果
const result = getAddResultFromServer('http://www.example.com?num1=1&num2=2');
// you get result  = "undefined"

如果你用普通函数相加两数字,你会马上获得结果。然而如果你发出一个远程调用来获得结果,那么你就需要等待,你不能马上得到结果。

或者这样说,你不知道会不会得到结果,因为服务器可能会性能下降,响应慢等等。你不希望因为等待着结果,让整个进程都被堵住。

调用API,下载文件,读取文件一些平时你会执行的异步操作。

Pomise 出现之前的世界: 回调(Callback)

我们一定要用 Prmoise 来做异步回调吗?不是的。优先于 promise ,我们用回调(callback)。回调(callback)仅仅是个你调用的函数,当你获得返回结果的时候。让我们修改之前的例子来获得一个回调。

// 远程相加两数字
// 调用API获得结果function addAsync (num1, num2, callback) {//使用有名的 jQuery getJSON 的回调 APIreturn $.getJSON('http://www.example.com', {num1: num1,num2: num2}, callback);
}addAsync(1, 2, success => {// callbackconst result = success; // 这里你得到 result = 3
}); 

这个语法看上去OK,为什么我们之后需要用 Promise ?

如果你想做一系列的异步操作怎么办??

比如说,不同于一次仅仅相加两个数字,我们希望加3次。用普通的函数,我们这么做:

// 普通相加两个数字let resultA, resultB, resultC;function add (num1, num2) {return num1 + num2;
}resultA = add(1, 2); // 你马上获得 resultA = 3
resultB = add(resultA, 3); // 你马上获得 esultB = 6
resultC = add(resultB, 4); // 你马上获得  resultC = 10console.log('total' + resultC);
console.log(resultA, resultB, resultC);

用了回调之后,这个看上去是什么样的?

// 远程相加两个数字
// 调用API获得结果let resultA, resultB, resultC;function addAsync (num1, num2, callback) {// use the famous jQuery getJSON callback APIreturn $.getJSON('http://www.example.com', {num1: num1,num2: num2}, callback);
}addAsync(1, 2, success => {// callback 1resultA = success; // you get result = 3 hereaddAsync(resultA, 3, success => {// callback 2resultB = success; // you get result = 6 hereaddAsync(resultB, 4, success => {// callback 3resultC = success; // you get result = 10 hereconsole.log('total' + resultC);console.log(resultA, resultB, resultC);});});
}); 

Demo: JS Bin - Collaborative JavaScript Debugging

这个语法很不友好。更贴切地说,这个看上去像金字塔,人们经常称呼为 "回调地狱",因为一个回调嵌在另一个回调之中。想象你有10个回调,你的代码嵌套了10次!

逃离回调地狱

Promise 来拯救你了。让我们看一下相同例子的 Promise 的版本。

// 使用observables,远程相加连个数字let resultA, resultB, resultC;function addAsync(num1, num2) {// 使用 ES6 抓取API, 这个返回一个 promisereturn fetch(`http://www.example.com?num1=${num1}&num2=${num2}`).then(x => x.json());
}addAsync(1, 2).then(success => {resultA = success;return resultA;}).then(success => addAsync(success, 3)).then(success => {resultB = success;return resultB;}).then(success => addAsync(success, 4)).then(success => {resultC = success;return resultC;}).then(success => {console.log('total: ' + success)console.log(resultA, resultB, resultC)}); 

Demo: JS Bin - Collaborative JavaScript Debugging

和 promise 我们用.then让回调在统一层次上。在某种程度上,这个看上去更加干净了,因为没有回调嵌套。当然,用 ES7 async 语法,我们可以加强这个例子,但是我把它留给你。:)

新鲜出炉的属性: 监控属性(observables)

在你搞定 Promise 之前,有样叫做Observables的东西出现了,这让你处理异步数据更加简单。

Observables 是懒惰的事件流,这个你可以提交0个或者更多的事件,并且可能不结束。

  • 来源https://cycle.js.org/streams.html

Promises 和 observables 之间几点关键的差异:

  • Observables 是可以取消的
  • Observables 是懒惰的

不要怕,让我们看看用 Observables 写相同demo。在这个例子中,我为 Observables 使用 RxJS。

let Observable = Rx.Observable;
let resultA, resultB, resultC;function addAsync(num1, num2) {// 用 ES6 抓取 API, 返回一个 promiseconst promise = fetch(`http://www.example.com?num1=${num1}&num2=${num2}`).then(x => x.json());return Observable.fromPromise(promise);
}addAsync(1,2).do(x => resultA = x).flatMap(x => addAsync(x, 3)).do(x => resultB = x).flatMap(x => addAsync(x, 4)).do(x => resultC = x).subscribe(x => {console.log('total: ' + x)console.log(resultA, resultB, resultC)}); 

Demo: JS Bin - Collaborative JavaScript Debugging

注意:

  • Observable.fromPromise 将一个 promise 转化为 Observable 流,
  • .do 和 .flatMap 是 observables 提供的操作符中的两个。
  • 流是懒惰的。当我们 .subscribe 它的时候,addAsync 才会运行。

Observables 可以简单地处理恶心的东西。比如,delay 添加 3 seconds 函数,只有一行代码或者充实,因此你可以重试一个调用一定的次数。

...addAsync(1,2).delay(3000) // delay 3 seconds.do(x => resultA = x)... 

有了 async/await 还需要学习 Promise 么?

Node.js 的异步编程方式有效提高了应用性能;

然而回调地狱却让人望而生畏,Promise 让我们告别回调函数,写出更优雅的异步代码;

在实践过程中,却发现 Promise 并不完美;

技术进步是无止境的,这时,我们有了 Async/Await。

虽然使用 Promise 能很好地解决回调地狱的问题,但是这种方式充满了 Promise 的 then() 方法,如果处理流程比较复杂的话,那么整段代码将充斥着 then,语义化不明显,代码不能很好地表示执行流程。

ES7中新增的异步编程方法,async/await的实现是基于 Promise的,简单而言就是async 函数就是返回Promise对象,是generator的语法糖。很多人认为async/await是异步操作的终极解决方案:

  • 语法简洁,更像是同步代码,也更符合普通的阅读习惯;
  • 改进JS中异步操作串行执行的代码组织方式,减少callback的嵌套;
  • Promise中不能自定义使用try/catch进行错误捕获,但是在Async/await中可以像处理同步代码处理错误。

不过也存在一些缺点,因为 await 将异步代码改造成了同步代码,如果多个异步代码没有依赖性却使用了 await 会导致性能上的降低。

参考:

Promise - JavaScript | MDNPromise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

es6中Promise的理解以及使用_飞歌Fly的博客-CSDN博客_promise的理解和使用转载:https://www.zcfy.cc/article/javascript-promises-for-dummies-scotch-1961.html理解 PromisePromise 简介:"假设你是一个宝宝. 你的妈妈承诺(Promise)你,下个礼拜她会给你一台新手机。"你不知道,下个礼拜你是否会拿到手机。你的妈妈可以真的给你买一个全新的手机,或者放你鸽子,也有可能如...https://blog.csdn.net/qq_35430000/article/details/86624419

你真的懂Promise吗 - 掘金在异步编程中,Promise 扮演了举足轻重的角色,比传统的解决方案(回调函数和事件)更合理和更强大。可能有些小伙伴会有这样的疑问:2020年了,怎么还在谈论Promise?事实上,有些朋友对于这个几乎每天都在打交道的“老朋友”,貌似全懂,但稍加深入就可能疑问百出,本文带大家深…https://juejin.cn/post/6844904132210655245

有了 async/await 还需要学习 Promise 么 - 知乎async/awaitnodejs 7.0 正式发布,并且增加了 async/await 功能,其原理类似于 co,使用 node --harmony-async-await app.js 就可以直接体验最新的 async/await 特性。 Why async/await 简单的一张图可以直观的表…https://zhuanlan.zhihu.com/p/23249103

Async/Await替代Promise的6个理由 | Fundebug博客 - 一行代码搞定BUG监控 - 网站错误监控|JS错误监控|资源加载错误|网络请求错误|小程序错误监控|Java异常监控|监控报警|Source Map|用户行为|可视化重现Async/Await替代Promise的6个理由https://blog.fundebug.com/2017/04/04/nodejs-async-await/

JavaScript Promise 对象 | 菜鸟教程ECMAscript 6 原生提供了 Promise 对象。 Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。 Promise 对象有以下两个特点: 1、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态: pending: 初始状态,不是成功或失败状态。 fulfilled: 意味着操作成功完成。 rejected: 意味着操作失败。 只有异步操作的结果,可以决定当前是哪一种状态,任何..https://www.runoob.com/w3cnote/javascript-promise-object.html

前端js进阶之ES6 Promise(承诺)用法小结笔记、详细解释(resolve,catch,catch)历史最通俗易懂的承诺相关推荐

  1. 自学JavaScript第四天- JS 进阶:AJAX Promise Canvas

    自学JavaScript第四天- JS 进阶:AJAX Promise Canvas AJAX 使用 XMLHttpRequest 使用 fetch() 方法 处理 AJAX 数据 安全限制 跨域方案 ...

  2. ES6 — Promise基础用法详解(resolve、reject、then、catch,all,)

    ES6 - Promise基础用法详解 Promise 是一个构造函数,它自身拥有all.reject.resolve这几个眼熟的方法, 原型上有then.catch等同样熟悉的方法. 所以,在开始一 ...

  3. js push(),pop(),unshift(),shift()的用法小结

    js中push(),pop(),unshift(),shift()的用法小结 1.push().pop()和unshift().shift() 这两组同为对数组的操作,并且会改变数组的本身的长度及内容 ...

  4. STL bitset用法小结(详细)附蓝桥杯题:明码

    bitset用法小结 使用bitset类型需引入头文件 #include< bitset > 它是一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1bit空间. bitset类 ...

  5. Vue基础知识总结 12:ES6 promise的用法总结

    目录 一.什么是Promise? 1.Promise是异步编程的一种解决方案 2.什么是回调地狱? 3.通过promise函数解决回调地狱的问题 二.Promise的三种状态 1.pending 2. ...

  6. mysql is exists_Mysql exists用法小结

    简介 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False. EXISTS 指定一个子查询,检测行的存在.语法:EXISTS subquer ...

  7. mysql exists怎么用_Mysql exists用法小结

    简介 EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False. EXISTS 指定一个子查询,检测行的存在.语法:EXISTS subquer ...

  8. Vue进阶(四十五):精解 ES6 Promise 用法

    文章目录 一.前言 二.链式操作用法 三.reject 用法 四.catch 用法 五.all 用法 六.race 用法 七.总结 八.拓展阅读 一.前言 复杂难懂概念先不讲,我们先简单粗暴地把Pro ...

  9. 前端点滴(JS进阶)(三)---- JavaScript 两链一包

    前端点滴(JS进阶)(三)----倾尽所有 一.作用域链 1. 作用域的概念 2. 作用域链 二.面向对象编程 1. 知识回顾 2. 定义对象 (1)new 内置对象 (2)直接量语法 (3)Es5 ...

最新文章

  1. 《强化学习周刊》第29期:Atari 深度强化学习的研究综述、金融强化学习的最新进展...
  2. python查找文件夹下的文件,python 查找文件夹下所有文件 实现代码 -电脑资料
  3. 怎么把原来的墙拆掉_电视墙避坑指南要收好!拆掉重装太心累...
  4. 语言相关系数显著性_ggplot2 绘制带星号和 Pvalue 值的相关系数热图
  5. uniapp uni.request GET方式请求,不能直接传数组解决方法
  6. mysql权重怎么配置_mysql如何按权重查询数据啊?
  7. java 实现 堆排序算法_C程序实现堆排序算法
  8. 面向对象的接口思想与函数式编程
  9. go json数据出现unicode_【Android】OkHttp、Retrofit拿到的json是Unicode,我要的是UTF-8呀...
  10. Repository 仓储,你的归宿究竟在哪?(三)-SELECT 某某某。。。
  11. 【c++leetcode】翻转链表
  12. 如何更改电脑开机密码
  13. bcdboot(引导修复工具) 命令行工具使用方法
  14. 企业微信如何快速共享打印
  15. win7游戏全屏模式通过注册表修改
  16. 进程管理API之pid_nr/pid_vnr/pid_nr_ns
  17. 交换机千兆和百兆对网速影响_千兆网线和百兆网线是否可以通用?
  18. C warning:statement with no effect [-Wunused-va...
  19. 跟sky学数字IC前端设计:数字IP_FPGA实战
  20. 2022年了总有一款软件是你需要的,9款软件测评

热门文章

  1. TDSQL-C 真·秒级启停:连接断了,又没断
  2. 拳皇97风云再起汉化版怎么调难度呀
  3. 管理思想之火象星座特质
  4. 计算机 小学数学应用题教学设计,小学数学解决问题的教案4篇
  5. MobaXterm连接虚拟机时出现Access denied
  6. Codeforces 699
  7. 用NPOI操作EXCEL-NPOI计算公式-通过NPOI获得公式的返回值
  8. 闪兼云提醒小白网络创业常见的骗局
  9. PuddingSwap布丁美食帝国原材料即将上线
  10. 中山一院——新一代的智慧医院建设,以流量分析为抓手,提升用户体验