整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Node.js 實現搶票小工具&短信通知提醒(下)「干貨」


          者:西嵐

          轉發鏈接:https://juejin.im/post/5dadd0236fb9a04de04d968e

          市屬廣播電視和網絡視聽行業統計單位:

          根據國家廣播電視總局相關要求,為確保2023年一季度廣播電視和網絡視聽統計工作順利進行,切實保障統計數據質量和報送時效,更好地發揮統計對廣播電視和網絡視聽發展的數據支持和引導作用,現就一季度統計報表工作提出具體要求:

          一、充分認識統計工作重要性,切實提高統計數據質量

          1.深化對統計工作重要性的認識。各廣播電視和網絡視聽統計填報單位要堅決貫徹落實黨的二十大、中央全面深化改革委員會第二十一次會議關于完善統計體制、發揮統計監督職能、提高統計數據質量、推進統計現代化改革的重大部署,認真學習貫徹執行《關于更加有效發揮統計監督職能作用的意見》《廣播電視行業統計管理規定》和《廣播電視和網絡視聽統計調查制度》,充分認識新時期廣播電視統計工作的重要性,增強做好統計工作的使命感和責任感,單位主要領導要親自過問,牢固樹立大局意識、責任意識、法制意識,強化部門之間的協作,保質、保量完成廣播電視行業統計工作。

          2.強化統計數據審核,建立初審、復審和復核制度。統計人員要嚴格按照《廣播電視和網絡視聽統計調查制度》要求填報統計數據,在數據填報過程中要注意表內、表間相關數據的邏輯關系,確保數據真實準確、不重不漏。各級匯總單位要強化報表數據審核,對每一項指標都要分區域、分單位認真進行同比、環比核對,并確保報表指標之間的邏輯關系準確。

          3.防范懲治統計造假,全面提升數據質量。堅決貫徹落實《防范和懲治統計造假、弄虛作假督察工作規定》《防范和懲治廣播電視和網絡視聽統計造假、弄虛作假責任制規定》文件精神,全面提升統計數據質量。各單位要認真履行統計法定義務、主動提供真實情況,明確統計機構和相關人員的主體責任,加強統計力量,配備專職或指定兼職統計人員,保持統計人員的相對穩定,提高廣播電視和網絡視聽統計數據的真實性、準確性和完整性。

          二、報送范圍

          北京廣播電視臺及所屬單位、北京歌華傳媒集團有限責任公司及所屬單位、北京歌華有線電視網絡股份有限公司、區融媒體中心、局所屬事業單位、持有《廣播電視節目制作經營許可證》和《信息網絡傳播視聽節目許可證》的機構等。

          三、報送時間

          2023年4月10日前。

          四、注意事項

          1.登錄系統填報表,請確認報表類型為“2023年一季度”。

          2.填報時請注意,上報數據為1-3月份的累計數,收入指標計量單位為“萬元”

          3.廣基19表03欄企業總收入,04欄實際創收收入,兩項必須同時填報。03欄企業單位總收入=主營業務收入+其他業務收入+補助收入;實際創收收入為廣播電視和網絡視聽相關收入。

          4.廣基19表22-23欄,沒有IPTV和OTT業務相關許可證的單位,請不要填寫。

          5.廣基20-1和20-2是影視節目出口和服務貿易出口表,有相關業務按合同填報,沒有相關業務的單位不填此表,也不點擊保存上報(保持報表狀態為未填報)。

          6.報表填報完畢后,需按附件2《季報說明對比模板》做說明和季度對比,并在直報系統“制度信息打印及文件上傳”模塊上傳一季度說明后,季報統計報送工作才全部完成。

          五、相關咨詢電話

          在報表編制、報送過程中,如遇指標解釋、填報口徑等問題,請與規劃發展處(產業促進處)聯系。

          聯系電話:

          010-86098124

          010-86098054

          QQ群號(廣電資質G群):

          621726350(申請入群請備注公司名稱)

          附件1:季報報送操作流程

          附件2:季報說明對比模板



          官網鏈接:http://gdj.beijing.gov.cn/zwxx/tzgg2/202304/t20230404_2974588.html

          文同步本人掘金平臺原創翻譯的文章:https://juejin.cn/post/6844903834246971400

          你是否遇到過"callbacks"一詞,但是不知道這意味著什么?別著急。你不是一個人。許多JavaScript的新手發現回調也很難理解。

          盡管callbacks可能令人疑惑,但是你仍然需要徹底了解它們,因為它們是JavaScript中的一個重要的概念。如果你不知道callbacks,你不可能走得很遠。

          這就是今天的文章(要講的)!你將了解callbacks是什么,為什么它們很重要,以及如何使用它們。

          備注:你會在這篇文章中看到ES6箭頭函數。如果你不是很熟悉它們,我建議你在往下讀之前復習一下ES6這篇文章(只了解箭頭函數部分就可以了)。

          callbacks是什么?

          callback是作為稍后要執行的參數傳遞給另一個函數的函數。(開發人員說你在執行函數時“調用”一個函數,這就是被命名為回調函數的原因)。

          它們在JavaScript中很常見,你可能自己潛意識的使用了它們而不知道它們被稱為回調函數。

          接受函數回調的一個示例是addEventLisnter:

          const button = document.querySelector('button')
          button.addEventListener('click', function(e) {
            // Adds clicked class to button
            this.classList.add('clicked')
          })
          復制代碼

          看不出是回調函數嗎?那么,這種寫法怎樣?

          const button = document.querySelector('button')
          
          // Function that adds 'clicked' class to the element
          function clicked (e) {
            this.classList.add('clicked')
          }
          
          // Adds click function as a callback to the event listener
          button.addEventListener('click', clicked)
          復制代碼

          在這里,我們告訴JavaScript監聽按鈕上的click事件。如果檢測到點擊,則JavaScript應觸發clicked函數。因此,在這種情況下,clicked是回調函數,而addEventListener是一個接受回調的函數。

          現在,你明白什么是回調函數了嘛?:)

          我們來看另外一個例子。這一次,假設你希望通過過濾一組數據來獲取小于5的列表。在這里,你將回調函數傳遞給filter函數:

          const numbers = [3, 4, 10, 20]
          const lesserThanFive = numbers.filter(num => num < 5)
          復制代碼

          現在,如果你想通過命名函數執行上面的代碼,則過濾函數將如下所示:

          const numbers = [3, 4, 10, 20]
          const getLessThanFive = num => num < 5
          
          // Passing getLessThanFive function into filter
          const lesserThanFive = numbers.filter(getLessThanFive)
          復制代碼

          在這種情況下,getLessThanFive是回調函數。Array.filter是一個接受回調的函數。

          現在明白為什么了吧?一旦你知道回調函數是什么,它們就無處不在!

          下面的示例向你展示如何編寫回調函數和接受回調的函數:

          // Create a function that accepts another function as an argument
          const callbackAcceptingFunction = (fn) => {
            // Calls the function with any required arguments
            return fn(1, 2, 3)
          }
          
          // Callback gets arguments from the above call
          const callback = (arg1, arg2, arg3) => {
            return arg1 + arg2 + arg3
          }
          
          // Passing a callback into a callback accepting function
          const result = callbackAcceptingFunction(callback)
          console.log(result) // 6
          復制代碼

          請注意,當你將回調函數傳遞給另一個函數時,你只傳遞該函數的引用(并沒有執行它,因此沒有括號())

          const result = callbackAcceptingFunction(callback)
          復制代碼

          你只能在callbackAcceptingFunction中喚醒(調用)回調函數。執行此操作時,你可以傳遞回調函數可能需要的任意數量的參數:

          const callbackAcceptingFunction = (fn) => {
            // Calls the callback with three args
            fn(1, 2, 3)
          }
          復制代碼

          這些由callbackAcceptingFunction傳遞給回調函數的參數,然后再通過回調函數(執行):

          // Callback gets arguments from callbackAcceptingFunction
          const callback = (arg1, arg2, arg3) => {
            return arg1 + arg2 + arg3
          }
          復制代碼

          這是回調的解剖。現在,你應該知道addEventListener包含一個event參數:)

          // Now you know where this event object comes from! :)
          button.addEventListener('click', (event) => {
            event.preventDefault()
          })
          復制代碼

          唷!這是callbacks的基本思路!只需要記住其關鍵:將一個函數傳遞給另一個函數,然后,你會想起我上面提到的機制。

          旁注:這種傳遞函數的能力是一件很重要的事情。它是如此重要,以至于說JavaScript中的函數是高階函數。高階函數在編程范例中稱為函數編程,是一件很重大的事情。

          但這是另一天的話題。現在,我確信你已經開始明白callbacks是什么,以及它們是如何被使用的。但是為什么?你為什么需要callbacks呢?

          為什么使用callbacks

          回調函數以兩種不同的方式使用 -- 在同步函數和異步函數中。

          同步函數中的回調

          如果你的代碼從上到下,從左到右的方式順序執行,等待上一個代碼執行之后,再執行下一行代碼,則你的代碼是同步的

          讓我們看一個示例,以便更容易理解:

          const addOne = (n) => n + 1
          addOne(1) // 2
          addOne(2) // 3
          addOne(3) // 4
          addOne(4) // 5
          復制代碼

          在上面的例子中,addOne(1)首先執行。一旦它執行完,addOne(2)開始執行。一旦addOne(2)執行完,addOne(3)執行。這個過程一直持續到最后一行代碼執行完畢。

          當你希望將部分代碼與其它代碼輕松交換時,回調將用于同步函數。

          所以,回到上面的Array.filter示例中,盡管我們將數組過濾為包含小于5的數組,但你可以輕松地重用Array.filter來獲取大于10的數字數組:

          const numbers = [3, 4, 10, 20]
          const getLessThanFive = num => num < 5
          const getMoreThanTen = num => num > 10
          
          // Passing getLessThanFive function into filter
          const lesserThanFive = numbers.filter(getLessThanFive)
          
          // Passing getMoreThanTen function into filter
          const moreThanTen = numbers.filter(getMoreThanTen)
          復制代碼

          這就是為什么你在同步函數中使用回調函數的原因。現在,讓我們繼續看看為什么我們在異步函數中使用回調。

          異步函數中的回調

          這里的異步意味著,如果JavaScript需要等待某些事情完成,它將在等待時執行給予它的其余任務。

          異步函數的一個示例是setTimeout。它接受一個回調函數以便稍后執行:

          // Calls the callback after 1 second
          setTimeout(callback, 1000)
          復制代碼

          如果你給JavaScript另外一個任務需要完成,讓我們看看setTimeout是如何工作的:

          const tenSecondsLater = _ = > console.log('10 seconds passed!')
          
          setTimeout(tenSecondsLater, 10000)
          console.log('Start!')
          復制代碼

          在上面的代碼中,JavaScript會執行setTimeout。然后,它會等待10秒,之后打印出"10 seconds passed!"的消息。

          同時,在等待setTimeout10秒內完成時,JavaScript執行console.log("Start!")。

          所以,如果你(在控制臺上)打印上面的代碼,這就是你會看到的:

          // What happens:
          // > Start! (almost immediately)
          // > 10 seconds passed! (after ten seconds)
          復制代碼

          啊~異步操作聽起來很復雜,不是嗎?但為什么我們在JavaScript中頻繁使用它呢?

          要了解為什么異步操作很重要呢?想象一下JavaScript是你家中的機器人助手。這個助手非常愚蠢。它一次只能做一件事。(此行為被稱為單線程)。

          假設你告訴你的機器人助手為你訂購一些披薩。但機器人是如此的愚蠢,在打電話給披薩店之后,機器人坐在你家門前,等待披薩送達。在此期間它無法做任何其它事情。

          你不能叫它去熨衣服,拖地或在等待(披薩到來)的時候做任何事情。(可能)你需要等20分鐘,直到披薩到來,它才愿意做其他事情...

          此行為稱為阻塞。當你等待某些內容完成時,其他操作將被阻止。

          const orderPizza = flavour => {
            callPizzaShop(`I want a ${flavour} pizza`)
            waits20minsForPizzaToCome() // Nothing else can happen here
            bringPizzaToYou()
          }
          
          orderPizza('Hawaiian')
          
          // These two only starts after orderPizza is completed
          mopFloor()
          ironClothes()
          復制代碼

          而阻止操作是一個無賴。

          為什么?

          讓我們把愚蠢的機器人助手放到瀏覽器的上下文中。想象一下,當單擊按鈕時,你告訴它更改按鈕的顏色。

          這個愚蠢的機器人會做什么?

          它專注于按鈕,忽略所有命令,直到按鈕被點擊。同時,用戶無法選擇任何其他內容。看看它都在干嘛了?這就是異步編程在JavaScript中如此重要的原因。

          但是,要真正了解異步操作期間發生的事情,我們需要引入另外一個東西 -- 事件循環。

          事件循環

          為了設想事件循環,想象一下JavaScript是一個攜帶todo-list的管家。此列表包含你告訴它要做的所有事情。然后,JavaScript將按照你提供的順序逐個遍歷列表。

          假設你給JavaScript下面五個命令:

          const addOne = (n) => n + 1
          
          addOne(1) // 2
          addOne(2) // 3
          addOne(3) // 4
          addOne(4) // 5
          addOne(5) // 6
          復制代碼

          這是JavaScript的待辦事項列表中出現的內容。

          相關命令在JavaScript待辦事項列表中同步出現。

          除了todo-list之外,JavaScript還保留一個waiting-list來跟蹤它需要等待的事情。如果你告訴JavaScript訂購披薩,它會打電話給披薩店并在等候列表名單中添加“等待披薩到達”(的指令)。與此同時,它還會做了其他已經在todo-list上的事情。

          所以,想象下你有下面代碼:

          const orderPizza (flavor, callback) {
            callPizzaShop(`I want a ${flavor} pizza`)
          
            // Note: these three lines is pseudo code, not actual JavaScript
            whenPizzaComesBack {
              callback()
            }
          }
          
          const layTheTable = _ => console.log('laying the table')
          
          orderPizza('Hawaiian', layTheTable)
          mopFloor()
          ironClothes()
          復制代碼

          JavaScript的初始化todo-list如下:

          訂披薩,拖地和熨衣服!

          然后,在執行orderPizza時,JavaScript知道它需要等待披薩送達。因此,它會在執行其余任務時,將“等待披薩送達”(的指令)添加到waiting list上。

          JavaScript等待披薩到達

          當披薩到達時,門鈴會通知JavaScript,當它完成其余雜務時。它會做個**心理記錄(mental note)**去執行layTheTable。

          JavaScript知道它需要通過在其 mental note 中添加命令來執行layTheTable

          然后,一旦完成其他雜務,JavaScript就會執行回調函數layTheTable。

          其他所有內容完成后,JavaScript就會去布置桌面(layTheTable)

          我的朋友,這個就被稱為事件循環。你可以使用事件循環中的實際關鍵字替換我們的管家,類比來理解所有的內容:

          • Todo-list -> Call stack
          • Waiting-list -> Web apis
          • Mental note -> Event queue

          JavaScript的事件循環

          如果你有20分鐘的空余時間,我強烈建議你觀看Philip Roberts 在JSconf中談論的事件循環。它將幫助你理解事件循環的細節。

          厄...那么,為什么callbacks那么重要呢?

          哦~我們在事件循環繞了一大圈。我們回正題吧。

          之前,我們提到如果JavaScript專注于按鈕并忽略所有其他命令,那將是不好的。是吧?

          通過異步回調,我們可以提前提供JavaScript指令而無需停止整個操作

          現在,當你要求JavaScript查看點擊按鈕時,它會將“監聽按鈕”(指令)放入waiting list中并繼續進行雜務。當按鈕最終獲得點擊時,JavaScript會激活回調,然后繼續執行。

          以下是回調中的一些常見用法,用于告訴JavaScript要做什么...

          1. 當事件觸發時(比如addEventListener)
          2. 在AJAX調用后(比如jQuery.ajax)
          3. 在讀/寫文件之后(比如fs.readFile)
          // Callbacks in event listeners
          document.addEventListener(button, highlightTheButton)
          document.removeEventListener(button, highlightTheButton)
          
          // Callbacks in jQuery's ajax method
          $.ajax('some-url', {
            success (data) { /* success callback */ },
            error (err) { /* error callback */}
          });
          
          // Callbacks in Node
          fs.readFile('pathToDirectory', (err, data) => {
            if (err) throw err
            console.log(data)
          })
          
          // Callbacks in ExpressJS
          app.get('/', (req, res) => res.sendFile(index.html))
          復制代碼

          這就是它(異步)的回調!

          希望你清楚callbacks是什么以及現在如何使用它們。在開始的時候,你不會創建很多回調,所以要專注于學習如何使用可用的回調函數。

          現在,在我們結束(本文)之前,讓我們看一下開發人員(使用)回調的第一個問題 -- 回調地獄。

          回調地獄

          回調地獄是一種多次回調相互嵌套的現象。當你執行依賴于先前異步活動的異步活動時,可能會發生這種情況。這些嵌套的回調使代碼更難閱讀。

          根據我的經驗,你只會在Node中看到回調地獄。在使用前端JavaScript時,你幾乎從不會遇到回調地獄。

          下面是一個回調地獄的例子:

          // Look at three layers of callback in this code!
          app.get('/', function (req, res) {
            Users.findOne({ _id:req.body.id }, function (err, user) {
              if (user) {
                user.update({/* params to update */}, function (err, document) {
                  res.json({user: document})
                })
              } else {
                user.create(req.body, function(err, document) {
                  res.json({user: document})
                })
              }
            })
          })
          復制代碼

          而現在,你有個挑戰 -- 嘗試一目了然地破譯上面的代碼。很難,不是嗎?難怪開發者在看到嵌套回調時會不寒而栗。

          克服回調地獄的一個解決方案是將回調函數分解為更小的部分以減少嵌套代碼的數量:

          const updateUser = (req, res) => {
            user.update({/* params to update */}, function () {
              if (err) throw err;
              return res.json(user)
            })
          }
          
          const createUser = (req, res, err, user) => {
            user.create(req.body, function(err, user) {
              res.json(user)
            })
          }
          
          app.get('/', function (req, res) {
            Users.findOne({ _id:req.body.id }, (err, user) => {
              if (err) throw err
              if (user) {
                updateUser(req, res)
              } else {
                createUser(req, res)
              }
            })
          })
          復制代碼

          更容易閱讀了,是吧?

          還有其他解決方案來對抗新版JavaScript中的回調地獄 -- 比如promises和async / await。但是,解釋它們是我們另一天的話題。

          結語

          今天,你了解到了回調是什么,為什么它們在JavaScript中如此重要以及如何使用它們。你還學會了回調地獄和對抗它的方法。現在,希望callbakcs不再嚇到你了。

          你對回調還有任何疑問嗎?如果你有,請隨時在下面發表評論,我會盡快回復你的。【PS:本文譯文,若需作者解答疑問,請移步原作者文章下評論】

          感謝閱讀。這篇文章是否幫助到你?如果有,我希望你考慮分享它。你可能會幫助到其他人。非常感謝!


          主站蜘蛛池模板: 国产一区二区三区播放心情潘金莲 | 久久亚洲AV午夜福利精品一区| 精品国产一区二区三区www| 日本精品一区二区三区四区| 日本高清无卡码一区二区久久 | 激情内射亚洲一区二区三区爱妻| 亚洲蜜芽在线精品一区| 无码人妻精品一区二区三区99性| 亚洲AV无码一区二区乱子伦| 中文激情在线一区二区| 亚洲国产视频一区| 国产高清精品一区| 国产成人AV一区二区三区无码 | 五十路熟女人妻一区二区 | 午夜视频一区二区| 亚洲一区精品中文字幕| 亚洲av乱码中文一区二区三区| 人妻无码一区二区不卡无码av| 成人精品一区二区三区电影| 亚洲国产精品一区二区久久hs| 色综合视频一区中文字幕| 久久er99热精品一区二区| 成人精品一区久久久久| а天堂中文最新一区二区三区| 久久一区二区三区精品| 精品伦精品一区二区三区视频| 中文字幕一区二区三区精彩视频| 日韩精品区一区二区三VR| 久久精品国产一区二区三区| 精品一区二区三区自拍图片区| 无码人妻一区二区三区免费| 国产怡春院无码一区二区 | 日本精品一区二区三区四区| 伊人无码精品久久一区二区| 久久久久人妻一区精品| 国模私拍一区二区三区| 久久一区二区三区免费播放| 亚洲中文字幕无码一区| 国产精品成人一区无码| 国产精品视频一区二区三区不卡| 无码毛片视频一区二区本码|