JavaScript —從回調到異步/等待

JavaScript is synchronous. This means that it will execute your code block by order after hoisting. Before the code executes, var and function declarations are “hoisted” to the top of their scope.

JavaScript是同步的。 這意味著它將在提升后按順序執行代碼塊。 在代碼執行之前,將varfunction聲明“提升”到其作用域的頂部。

This is an example of a synchronous code:

這是一個同步代碼的示例:

console.log('1')console.log('2')console.log('3')

This code will reliably log “1 2 3".

此代碼將可靠地記錄為“ 1 2 3”。

Asynchronous requests will wait for a timer to finish or a request to respond while the rest of the code continues to execute. Then when the time is right a callback will spring these asynchronous requests into action.

異步請求將等待計時器完成或請求響應,而其余代碼將繼續執行。 然后,當時間合適時, 回調將使這些異步請求生效。

This is an example of an asynchronous code:

這是一個異步代碼的示例:

console.log('1')setTimeout(function afterTwoSeconds() {console.log('2')
}, 2000)console.log('3')

This will actually log “1 3 2”, since the “2” is on a setTimeout which will only execute, by this example, after two seconds. Your application does not hang waiting for the two seconds to finish. Instead it keeps executing the rest of the code and when the timeout is finished it returns to afterTwoSeconds.

實際上,這將記錄為“ 1 3 2”,因為“ 2”位于setTimeout上,在此示例中,僅在兩秒鐘后執行。 您的應用程序不會掛起等待兩秒鐘。 相反,它將繼續執行其余代碼,并且當超時完成時,它將返回至afterTwoSeconds。

You may ask “Why is this useful?” or “How do I get my async code to become sync?”. Hopefully I can show you the answers.

您可能會問“為什么這有用?” 或“如何使我的異步代碼變得同步?”。 希望我能給你答案。

“問題” (“The problem”)

Let us say our goal is to search for a GitHub user and get all the repositories of that user. The thing is we don’t know the exact name of the user. So we have to list all the users with similar name and their respective repositories.

讓我們說我們的目標是搜索GitHub用戶并獲取該用戶的所有存儲庫。 問題是我們不知道用戶的確切名稱。 因此,我們必須列出名稱相似的所有用戶及其各自的存儲庫。

Doesn’t need to super fancy, something like this

不需要花哨的東西,像這樣

In these examples the request code will use XHR (XMLHttpRequest). You can replace it with jQuery $.ajax or the more recent native approach called fetch. Both will give you the promises approach out of the gate.

在這些示例中,請求代碼將使用XHR( XMLHttpRequest )。 您可以將其替換為jQuery $.ajax或較新的本地方法fetch 。 兩者都會使您脫穎而出。

It will be slightly changed depending on your approach but as a starter:

首先,它會根據您的方法稍有變化:

// url argument can be something like 'https://api.github.com/users/daspinola/repos'function request(url) {const xhr = new XMLHttpRequest();xhr.timeout = 2000;xhr.onreadystatechange = function(e) {if (xhr.readyState === 4) {if (xhr.status === 200) {// Code here for the server answer when successful} else {// Code here for the server answer when not successful}}}xhr.ontimeout = function () {// Well, it took to long do some code here to handle that}xhr.open('get', url, true)xhr.send();
}

Remember that in these examples the important part is not what the end result of the code is. Instead your goal should be to understand the differences of the approaches and how you can leverage them for your development.

請記住,在這些示例中,重要的部分不是代碼的最終結果。 相反,您的目標應該是了解方法的差異以及如何利用它們進行開發。

打回來 (Callback)

You can save a reference of a function in a variable when using JavaScript. Then you can use them as arguments of another function to execute later. This is our “callback”.

使用JavaScript時,可以將函數的引用保存在變量中。 然后,您可以將它們用作另一個函數的參數,以便以后執行。 這是我們的“回調”。

One example would be:

一個例子是:

// Execute the function "doThis" with another function as parameter, in this case "andThenThis". doThis will execute whatever code it has and when it finishes it should have "andThenThis" being executed.doThis(andThenThis)// Inside of "doThis" it's referenced as "callback" which is just a variable that is holding the reference to this functionfunction andThenThis() {console.log('and then this')
}// You can name it whatever you want, "callback" is common approachfunction doThis(callback) {console.log('this first')// the '()' is when you are telling your code to execute the function reference else it will just log the referencecallback()
}

Using the callback to solve our problem allows us to do something like this to the request function we defined earlier:

使用callback來解決我們的問題,使我們可以對之前定義的request函數執行以下操作:

function request(url, callback) {const xhr = new XMLHttpRequest();xhr.timeout = 2000;xhr.onreadystatechange = function(e) {if (xhr.readyState === 4) {if (xhr.status === 200) {callback(null, xhr.response)} else {callback(xhr.status, null)}}}xhr.ontimeout = function () {console.log('Timeout')}xhr.open('get', url, true)xhr.send();
}

Our function for the request will now accept a callback so that when a request is made it will be called in case of error and in case of success.

現在,我們用于請求的函數將接受callback以便在發出request時將在錯誤和成功的情況下調用它。

const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users`request(userGet, function handleUsersList(error, users) {if (error) throw errorconst list = JSON.parse(users).itemslist.forEach(function(user) {request(user.repos_url, function handleReposList(err, repos) {if (err) throw err// Handle the repositories list here})})
})

Breaking this down:

分解如下:

  • We make a request to get a user’s repositories

    我們請求獲取用戶的存儲庫
  • After the request is complete we use callback handleUsersList

    請求完成后,我們使用回調handleUsersList

  • If there is no error then we parse our server response into an object using JSON.parse

    如果沒有錯誤,則使用JSON.parse服務器響應解析為一個對象

  • Then we iterate our user list since it can have more than one

    然后,我們迭代用戶列表,因為它可以有多個

    For each user we request their repositories list.

    對于每個用戶,我們都請求他們的存儲庫列表。

    We will use the url that returned per user in our first response

    我們將在第一個響應中使用每個用戶返回的網址

    We call

    我們稱之為

    repos_urlas the url for our next requests or from the first response

    repos_url作為下一個請求或第一個響應的URL

  • When the request has completed the callback, we will call

    當請求完成回調后,我們將調用

    This will handle either its error or the response with the list of repositories for that user

    這將使用該用戶的存儲庫列表來處理其錯誤或響應

Note: Sending the error first as parameter is a common practice especially when using Node.js.

注意 :通常首先發送錯誤作為參數,尤其是在使用Node.js時。

A more “complete” and readable approach would be to have some error handling. We would keep the callback separate from the request execution.

一種更“完整”且易讀的方法是要進行一些錯誤處理。 我們將使回調與請求執行分開。

Something like this:

像這樣:

try {request(userGet, handleUsersList)
} catch (e) {console.error('Request boom! ', e)
}function handleUsersList(error, users) {if (error) throw errorconst list = JSON.parse(users).itemslist.forEach(function(user) {request(user.repos_url, handleReposList)})
}function handleReposList(err, repos) {if (err) throw err// Handle the repositories list hereconsole.log('My very few repos', repos)
}

This ends up having problems like racing and error handling issues. Racing happens when you don’t control which user you will get first. We are requesting the information for all of them in case there is more than one. We are not taking an order into account. For example, user 10 can come first and user 2 last. We have a possible solution later in the article.

最終會出現競速和錯誤處理問題。 當您無法控制將首先獲得哪個用戶時,就會發生競速。 如果不止一個,我們要求提供所有這些信息。 我們沒有考慮訂單。 例如,用戶10可以排在第一位,而用戶2可以排在最后。 我們將在本文后面提供一個可能的解決方案。

The main problem with callbacks is that maintenance and readability can become a pain. It sort of already is and the code does hardly anything. This is known as callback hell which can be avoided with our next approach.

回調的主要問題是維護和可讀性會變得很痛苦。 它已經存在,并且代碼幾乎沒有任何作用。 這被稱為回調地獄 ,可以通過我們的下一種方法來避免。

承諾 (Promises)

Promises you can make your code more readable. A new developer can come to the code base and see a clear order of execution to your code.

保證您可以使代碼更具可讀性。 新的開發人員可以進入代碼庫,并查看代碼的清晰執行順序。

To create a promise you can use:

要創建承諾,您可以使用:

const myPromise = new Promise(function(resolve, reject) {// code hereif (codeIsFine) {resolve('fine')} else {reject('error')}})myPromise.then(function whenOk(response) {console.log(response)return response}).catch(function notOk(err) {console.error(err)})

Let us decompose it:

讓我們分解一下:

  • A promise is initialized with a function that has resolve and reject statements

    使用具有resolvereject語句的function初始化promise

  • Make your async code inside the Promise function

    使您的異步代碼在Promise函數中

    Make your async code inside the Promise functionresolve when everything happens as desired

    當一切都按需進行時,使Promise函數中的異步代碼Promise resolve

    Otherwise

    除此以外

    reject

    reject

  • When a resolve is found the .then method will execute for that Promise

    找到resolve.then方法將針對該Promise執行

    When a

    當一個

    reject is found the .catch will be triggered

    發現reject ,將觸發.catch

Things to bear in mind:

注意事項:

  • resolve and reject only accept one parameter

    resolvereject僅接受一個參數

    resolve and reject only accept one parameterresolve(‘yey’, ‘works’) will only send ‘yey’ to the .then callback function

    resolvereject只接受一個參數resolve('yey', 'works')將只發送“yey”到.then回調函數

  • If you chain multiple .then

    如果鏈接多個.then

    Add a

    添加一個

    return if you want the next .then value not to be undefined

    return如果你想下一個.then值不被undefined

  • When a reject is caught with .catch if you have a .then chained to it

    當一個reject被抓到.catch如果你有一個.then鏈接到它

    It will still execute that

    它仍然會執行

    .then

    .then

    You can see the

    你可以看到

    .then as an “always executes” and you can check an example in this comment

    .then作為“始終執行”,您可以在此注釋中查看示例

  • With a chain on .then if an error happens on the first one

    如果鏈上.then如果第一個發生錯誤

    It will skip subsequent

    隨后將跳過

    .then until it finds a .catch

    .then ,直到找到一個.catch

  • A promise has three states

    一個承諾有三個狀態

    A promise has three statespending

    一個承諾有三個待處理狀態

  • When waiting for a resolve or reject to happen

    等待resolvereject發生時

    When waiting for a resolve or reject to happenresolved

    當等待resolvereject發生解決時

    When waiting for a resolve or reject to happenresolved rejected

    在等待resolvereject發生時, 解決 被拒絕

  • Once it’s in a resolved or rejected state

    一旦處于已resolved或已rejected狀態

    It cannot be changed

    不能改變

Note: You can create promises without the function at the moment of declarations. The way that I’m showing it is only a common way of doing it.

注意 :在聲明時,您可以創建沒有功能的promise。 我展示它的方式只是這樣做的一種常見方式。

“Theory, theory, theory…I’m confused” you may say.

您可能會說:“理論,理論,理論……我很困惑”。

Let’s use our request example with a promise to try to clear things up:

讓我們將請求示例與一個承諾一起使用來嘗試清除問題:

function request(url) {return new Promise(function (resolve, reject) {const xhr = new XMLHttpRequest();xhr.timeout = 2000;xhr.onreadystatechange = function(e) {if (xhr.readyState === 4) {if (xhr.status === 200) {resolve(xhr.response)} else {reject(xhr.status)}}}xhr.ontimeout = function () {reject('timeout')}xhr.open('get', url, true)xhr.send();})
}

In this scenario when you execute request it will return something like this:

在這種情況下,當您執行request ,它將返回如下內容:

const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users`const myPromise = request(userGet)console.log('will be pending when logged', myPromise)myPromise.then(function handleUsersList(users) {console.log('when resolve is found it comes here with the response, in this case users ', users)const list = JSON.parse(users).itemsreturn Promise.all(list.map(function(user) {return request(user.repos_url)}))}).then(function handleReposList(repos) {console.log('All users repos in an array', repos)}).catch(function handleErrors(error) {console.log('when a reject is executed it will come here ignoring the then statement ', error)})

This is how we solve racing and some of the error handling problems. The code is still a bit convoluted. But its a way to show you that this approach can also create readability problems.

這就是我們解決賽車以及一些錯誤處理問題的方式。 代碼仍然有些復雜。 但是,這是一種向您展示這種方法還會造成可讀性問題的方法。

A quick fix would be to separate the callbacks like so:

一個快速的解決方法是像這樣將回調分開:

const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users`const userRequest = request(userGet)// Just by reading this part out loud you have a good idea of what the code does
userRequest.then(handleUsersList).then(repoRequest).then(handleReposList).catch(handleErrors)function handleUsersList(users) {return JSON.parse(users).items
}function repoRequest(users) {return Promise.all(users.map(function(user) {return request(user.repos_url)}))
}function handleReposList(repos) {console.log('All users repos in an array', repos)
}function handleErrors(error) {console.error('Something went wrong ', error)
}

By looking at what userRequest is waiting in order with the .then you can get a sense of what we expect of this code block. Everything is more or less separated by responsibility.

通過查看與userRequest等待的userRequest .then您可以了解我們對這個代碼塊的期望。 一切或多或少都由責任分隔。

This is “scratching the surface” of what Promises are. To have a great insight on how they work I cannot recommend enough this article.

這就是“承諾”的“表面”。 要對它們的工作原理有一個深刻的了解,我不能推薦這篇文章 。

發電機 (Generators)

Another approach is to use the generators. This is a bit more advance so if you are starting out feel free to jump to the next topic.

另一種方法是使用發電機。 這還有一些進步,因此,如果您剛開始,請隨時跳到下一個主題。

One use for generators is that they allow you to have async code looking like sync.

生成器的一種用途是,它們使您可以擁有看起來像同步的異步代碼。

They are represented by a * in a function and look something like:

它們在函數中由*表示,外觀類似于:

function* foo() {yield 1const args = yield 2console.log(args)
}
var fooIterator = foo()console.log(fooIterator.next().value) // will log 1
console.log(fooIterator.next().value) // will log 2fooIterator.next('aParam') // will log the console.log inside the generator 'aParam'

Instead of returning with a return, generators have a yield statement. It stops the function execution until a .next is made for that function iteration. It is similar to .then promise that only executes when resolved comes back.

生成器具有yield語句,而不是返回return 。 它會停止函數執行,直到為該函數迭代創建.next為止。 它類似于.then承諾,僅在解決方案返回時才執行。

Our request function would look like this:

我們的請求函數如下所示:

function request(url) {return function(callback) {const xhr = new XMLHttpRequest();xhr.onreadystatechange = function(e) {if (xhr.readyState === 4) {if (xhr.status === 200) {callback(null, xhr.response)} else {callback(xhr.status, null)}}}xhr.ontimeout = function () {console.log('timeout')}xhr.open('get', url, true)xhr.send()}
}

We want to have the url as an argument. But instead of executing the request out of the gate we want it only when we have a callback to handle the response.

我們希望將url作為參數。 但是,僅當我們具有處理響應的回調時,我們才需要它,而不是從門外執行請求。

Our generator would be something like:

我們的generator將是這樣的:

function* list() {const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users`const users = yield request(userGet)yieldfor (let i = 0; i<=users.length; i++) {yield request(users[i].repos_url)}
}

It will:

它會:

  • Wait until the first request is prepared

    等到第一個request準備好

  • Return a function reference expecting a callback for the first request

    返回一個function引用,期望第一個requestcallback

    Our

    我們的

    request function accepts a url

    request函數接受url

    and returns a

    并返回一個

    function that expects a callback

    需要callback function

  • Expect a users to be sent in the next .next

    期望在下一個.next發送users

  • Iterate over users

    遍歷users

  • Wait for a .next for each of the users

    等待每個users.next

  • Return their respective callback function

    返回各自的回調函數

So an execution of this would be:

因此,將執行以下操作:

try {const iterator = list()iterator.next().value(function handleUsersList(err, users) {if (err) throw errconst list = JSON.parse(users).items// send the list of users for the iteratoriterator.next(list)list.forEach(function(user) {iterator.next().value(function userRepos(error, repos) {if (error) throw repos// Handle each individual user repo hereconsole.log(user, JSON.parse(repos))})})})  
} catch (e) {console.error(e)
}

We could separate the callback functions like we did previously. You get the deal by now, a takeaway is that we now can handle each individual user repository list individually.

我們可以像以前一樣分離回調函數。 您現在就達成了交易,一個收獲是,我們現在可以分別處理每個單獨的用戶存儲庫列表。

I have mixed felling about generators. On one hand I can get a grasp of what is expected of the code by looking at the generator.

我對發電機一無所知。 一方面,通過查看生成器,我可以了解代碼的期望。

But its execution ends up having similar problems to the callback hell.

但是其執行最終會遇到與回調地獄類似的問題。

Like async/await, a compiler is recommended. This is because it isn’t supported in older browser versions.

與async / await一樣 ,建議使用編譯器。 這是因為較舊的瀏覽器版本不支持該功能。

Also it isn’t that common in my experience. So it may generate confusing in codebases maintained by various developers.

根據我的經驗,這也不是那么普遍。 因此,它可能會在由各種開發人員維護的代碼庫中引起混亂。

An awesome insight of how generators work can be found in this article. And here is another great resource.

在本文中可以找到有關生成器工作原理的真知灼見。 這是另一個很棒的資源 。

異步/等待 (Async/Await)

This method seems like a mix of generators with promises. You just have to tell your code what functions are to be async. And what part of the code will have to await for that promise to finish.

這種方法似乎是帶有承諾的生成器的混合體。 您只需要告訴您的代碼哪些函數將是async 。 以及代碼的哪一部分必須awaitpromise完成。

sumTwentyAfterTwoSeconds(10).then(result => console.log('after 2 seconds', result))async function sumTwentyAfterTwoSeconds(value) {const remainder = afterTwoSeconds(20)return value + await remainder
}function afterTwoSeconds(value) {return new Promise(resolve => {setTimeout(() => { resolve(value) }, 2000);});
}

In this scenario:

在這種情況下:

  • We have sumTwentyAfterTwoSeconds as being an async function

    我們將sumTwentyAfterTwoSeconds作為異步函數

  • We tell our code to wait for the resolve or reject for our promise function afterTwoSeconds

    afterTwoSeconds我們告訴我們的代碼等待我們的promise函數的resolvereject

  • It will only end up in the .then when the await operations finish

    它只會在await操作結束時以.then結尾

    In this case there is only one

    在這種情況下,只有一個

Applying this to our request we leave it as a promise as seen earlier:

將此應用于我們的request我們將其作為一個promise如先前所示:

function request(url) {return new Promise(function(resolve, reject) {const xhr = new XMLHttpRequest();xhr.onreadystatechange = function(e) {if (xhr.readyState === 4) {if (xhr.status === 200) {resolve(xhr.response)} else {reject(xhr.status)}}}xhr.ontimeout = function () {reject('timeout')}xhr.open('get', url, true)xhr.send()})
}

We create our async function with the needed awaits like so:

我們使用所需的等待創建async函數,如下所示:

async function list() {const userGet = `https://api.github.com/search/users?page=1&q=daspinola&type=Users`const users = await request(userGet)const usersList = JSON.parse(users).itemsusersList.forEach(async function (user) {const repos = await request(user.repos_url)handleRepoList(user, repos)})
}function handleRepoList(user, repos) {const userRepos = JSON.parse(repos)// Handle each individual user repo hereconsole.log(user, userRepos)
}

So now we have an async list function that will handle the requests. Another async is needed in the forEach so that we have the list of repos for each user to manipulate.

因此,現在我們有了一個異步list函數來處理請求。 forEach需要另一個異步,以便我們擁有供每個用戶操縱的存儲repos列表。

We call it as:

我們稱其為:

list().catch(e => console.error(e))

This and the promises approach are my favorites since the code is easy to read and change. You can read about async/await more in depth here.

由于易于閱讀和更改代碼,因此我最喜歡這種方法和Promise方法。 您可以在此處詳細了解異步/等待。

A downside of using async/await is that it isn’t supported in the front-end by older browsers or in the back-end. You have to use the Node 8.

使用async / await的缺點是舊版瀏覽器或后端不支持它的前端。 您必須使用節點8。

You can use a compiler like babel to help solve that.

您可以使用像babel這樣的編譯器來解決這個問題。

“解” (“Solution”)

You can see the end code accomplishing our initial goal using async/await in this snippet.

您可以在此代碼段中看到使用async / await完成我們最初目標的最終代碼 。

A good thing to do is to try it yourself in the various forms referenced in this article.

要做的一件好事是以本文引用的各種形式自己嘗試。

結論 (Conclusion)

Depending on the scenario you might find yourself using:

根據情況,您可能會發現自己使用:

  • async/await

    異步/等待
  • callbacks

    回叫
  • mix

    混合

It’s up to you what fits your purposes. And what lets you maintain the code so that it is understandable to others and your future self.

取決于您的目的。 什么使您能夠維護代碼,以便他人和您將來的自己可以理解。

Note: Any of the approaches become slightly less verbose when using the alternatives for requests like $.ajax and fetch.

注意:當對$.ajaxfetch類的請求使用替代方法時,任何一種方法的冗長程度都會略微降低。

Let me know what you would do different and different ways you found to make each approach more readable.

讓我知道您會采取什么不同的方式來發現每種方法,以使其更具可讀性。

This is Article 11 of 30. It is part of a project for publishing an article at least once a week, from idle thoughts to tutorials. Leave a comment, follow me on Diogo Spínola and then go back to your brilliant project!

這是30條中的第11條。它是一個項目的一部分,該項目每周至少發表一次文章,從無聊的想法到教程。 發表評論,關注我DiogoSpínola ,然后回到您的杰出項目!

翻譯自: https://www.freecodecamp.org/news/javascript-from-callbacks-to-async-await-1cc090ddad99/

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395310.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395310.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395310.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

關于解決工作中的自動化環境搭建的解決方案(序)

時間&#xff1a;2015~2017 之前的自動化搭建平臺&#xff1a;robotest 安裝工具&#xff1a;jdk1.8,robotest 這種工具反正超級好用&#xff0c;華為方搞得工具&#xff0c;前臺操作超級傻瓜。會點xpatch&#xff0c;一些東西根本不在話下。但是坑爹的就是&#xff0c;出了外包…

xshell安裝mysql步驟_mysql主從復制

前期提要&#xff1a;三年前雙11買的阿里云今年到期了&#xff0c;win2012的&#xff0c;上面mysql數據庫里記著自己的一些記賬數據&#xff0c;上一年雙11買了騰訊云的&#xff0c;centos7.7, 想學學MYSQL的復制功能&#xff0c;今天趁著無BUG可擼&#xff0c;試著配置了一下&…

大專學計算機維修,《計算機維修與網絡工程》大專學歷班

語文、數學、計算機英語、公文寫作等辦公自動化指法訓練、英文打字、智能拼音及高速五筆字型中文打字、windows操作、Word2003文字處理軟件、Excel2003電子表格、Powerpoint2003幻燈片制作、Internet網絡的上網方法、瀏覽、下載、電子郵件收發等。本班學習完畢&#xff0c;可獨…

webpack指定第三方模塊的查找路徑

通常我們會使用一些地方模塊在我們的項目中&#xff0c;比如bootstrap import bootstrap 導入的bootstrap默認會查找當前目錄的node_modules文件&#xff0c;但是如果這個文件沒有&#xff0c;會依次往上級模塊查找&#xff0c;直到到C盤的根目錄為止&#xff0c;可以通過webpa…

我的第一個安卓應用程序_我如何設計我的第一個應用程序

我的第一個安卓應用程序by Daniel Novykov丹尼爾諾維科夫(Daniel Novykov) 我如何設計我的第一個應用程序 (How I Designed My First App) This is a story about building a product, what went wrong, and how it changed my career into Design.這是一個有關構建產品&#…

Appium——主從控制執行

1.客戶端(Eclipse)機器A&#xff0c; 服務端(appium、Genymotion)機器B 2.設置Appium&#xff0c;Server Address為192.168.17.123&#xff0c;重新啟動Appium 3.在客戶端機器A瀏覽器中輸入&#xff1a;http://192.168.17.123:4723/wd/hub&#xff0c; 說明配置成功。 JAVA代碼…

Python學習-03(集合,文件,編碼)

上周復習&#xff1a; 列表增刪改查 元祖是可讀列表 字符串操作 字典是無序的&#xff0c;通過key來找值。字典可以嵌套列表和字典 本周內容&#xff1a;集合--文件---字符編碼 集合引入&#xff1a; #隨機生成20個小于20的數&#xff0c;輸出所有的數&#xff0c;# 要求重復…

安裝centos7失敗認不到硬盤_CentOS7 用U盤安裝卡住無法進入安裝界面解決方案

使用U盤安裝Centos系統找不到U盤解決方案補充&#xff1a;1、制作U盤啟動盤請參考&#xff1a;使用UltraISO(軟碟通)制作ubuntu U盤啟動盤如果你安裝centos7出現了下圖這種情況不用擔心&#xff0c;是因為安裝centos7時找不到U盤稍等一下&#xff0c;如下圖等到出現命令行時。輸…

Django橫向二級導航欄(鼠標懸空事件)

1 <!DOCTYPE html>2 <html lang"en" xmlns"http://www.w3.org/1999/html">3 <head>4 <meta charset"UTF-8">5 <title>{% block title %} base模板 {% endblock title%}</title>6 <style >…

浙江大學計算機學院1702班,測控1702:傳道授業解惑 此間師者真情

2017年9月11日晚8:00&#xff0c;電氣與信息工程學院測控技術與儀器1702班在德智學生公寓的天臺上開展了一場別開生面的班主任見面交流會。測控1702班班主任文一章博士、電氣院2017級本科輔導員金晶老師以及測控1702班的同學們參加了此次見面會。測控1702班班主任文一章1991年出…

通過小程序給公眾號傳遞消息_多輸入現場消息傳遞應用程序概念

通過小程序給公眾號傳遞消息by Dawid Woldu戴維德沃爾杜(Dawid Woldu) 多輸入現場消息傳遞應用程序概念 (A multi-input field messaging app concept) Some time ago I shared in a Medium article the idea for context aware messenger app. The idea challenged the desig…

Oracle【IT實驗室】數據庫備份與恢復之二:SQL*Loader

2.1 基本知識 Oracle 的 SQL* LOADER 可以將外部格式化的文本數據加載到數據庫表中。通常 與 SPOOL導出文本數據方法配合使用。 1.命令格式 SQLLDR keywordvalue [&#xff0c;keywordvalue&#xff0c;……] 例&#xff1a;$ sqlldr user/pwd controlemp.ctl dataemp.dat ba…

關于spring 獲取不到網站上的xsd的處理記錄

2019獨角獸企業重金招聘Python工程師標準>>> 前兩天做一個項目還好好的&#xff0c;今天突然報出這個錯誤 cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element mvc:annotation-driven 應該是xml文件找不到相應…

藍寶石英語怎么讀_黑金和藍寶石

這是一直以后我個人的一個理解誤區&#xff0c;或者說是信息誤區&#xff0c;就是這兩個產品線&#xff0c;差別到底在哪里&#xff1f;以前我一直認為黑金的成分是純天然的&#xff0c;而藍寶石有一定的合成物質。這個信息一定是我從哪里讀到的&#xff0c;由于無處求證&#…

秘密潛入2小辣椒_短暫潛入2次,我顯然不知道自己作為開發人員正在做什么

秘密潛入2小辣椒by Zachary Kuhn扎卡里庫恩(Zachary Kuhn) 那兩次我顯然不知道我作為開發人員正在做什么 (Those two times where I clearly had no clue what I was doing as a developer) Last week I had a short conversation with coworkers about how we had messed up …

提高你的javascript代碼逼格系列之函數與數組

不知道大家有沒有一種感覺&#xff0c;那就是自己寫的javascript代碼雖然能完全解決工作上的需要&#xff0c;但是&#xff0c;一眼望去&#xff0c;too simple&#xff01;&#xff01;&#xff01;簡直就是一個傻子都能看懂的水平&#xff0c;于是&#xff0c;在工作之余&…

印度評論九章量子計算機,張禮立:中國 “九章”量子計算機到底厲害在哪?...

【背景信息】12月4日&#xff0c;《科學》雜志公布了中國“九章”的重大突破。 這臺由中國科學技術大學潘建偉、陸朝陽等學者研制的76個光子的量子計算原型機&#xff0c;推動全球量子計算的前沿研究達到一個新高度。盡管距離實際應用仍有漫漫長路&#xff0c;但成功實現了“量…

手機web網頁制作的認識(有關meta標簽)

近日以來一直在看JQuery Mobile 一個手機開發框架&#xff0c;說實話真的很頭疼的~~~~ 因為里面有很多的屬性、方法和事件~~~ 下面是手機網頁的一些認識&#xff1a; 一、<meta name"viewport" id"viewport" content"widthdevice-width, initial-s…

包打包和解析過程 unity_Unity學習—資源管理概覽

本文介紹了 Unity 常用四種默認路徑&#xff0c;以及 AssetDataBase、Resources、AssetBundle 和目前最新的 Addressable 四種資源管理方式文中所有 API 均以版本 2019.3 為準本文原地址&#xff1a;Unity學習—資源管理概覽資源路徑Application.dataPath官方文檔只讀&#xff…

graphql tools_聲明式GraphQL:編寫更少的代碼,并使用graphql-tools完成更多工作

graphql toolsI’ve been working with GraphQL for a few months now, but only recently began using Apollo’s graphql-tools library. After learning a few idioms, I am able to mock up a functional API quickly. This is largely due to its low-code, declarative a…