亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

callback

tianren124 / 3594人閱讀

摘要:前言入門(mén)阮一峰另類(lèi)的實(shí)現(xiàn)同級(jí)別的另外一個(gè)函數(shù)。該事件系統(tǒng)允許代碼定義應(yīng)用程序的特定事件,該事件可以傳遞自定義參數(shù),自定義參數(shù)包含訂閱者所需要的值。其目的是避免訂閱者和發(fā)布者產(chǎn)生依賴關(guān)系。狀態(tài)轉(zhuǎn)變不可逆。方法必須返回一個(gè)。

callback 前言

ECMAScript 6入門(mén)(阮一峰)

setInterval: 另類(lèi)的callback實(shí)現(xiàn)

setInterval同級(jí)別的另外一個(gè)函數(shù):setTimeout。

設(shè)置n秒后,有一定時(shí)間延時(shí)的,2ms左右;

最低時(shí)間為4ms,參考傳送門(mén)

var d = new Date, count = 0, f, timer;
timer = setInterval(f = function (){
    if(new Date - d > 1000) {
        clearInterval(timer), console.log(count);
    }
    count++;
}, 0);

setTimeout中的錯(cuò)誤使用try,catch不可捕獲

try{
    setTimeout(function(){
        throw new Error("我不希望這個(gè)錯(cuò)誤出現(xiàn)!")
    }, 1000);
} catch(e){
    console.log(e.message);
}
callback: 常用的javascript回調(diào)

通常作為參數(shù)進(jìn)行傳遞

function getData(callback) {
    $.ajax({
        url: "",
        success: resp => {
            callback(resp);
        }
    });
}
getData(resp => {
    // write your code here
});

調(diào)用的時(shí)候,可以直接調(diào)用,還可以通過(guò)bind,call,apply指定當(dāng)前作用域

function getData(callback) {
    $.ajax({
        url: "",
        success: resp => {
            callback(resp.data);
            callback.bind(null)(resp.data);
            callback.call(null, resp.data);
            callback.apply(null, resp.data);
        }
    });
}
getData((...resp) => {
    // write your code here
});
事件監(jiān)聽(tīng): 一般用作dom的事件綁定

1.js自定義事件監(jiān)聽(tīng):

let myEvents = new MyEvent();
myEvents.addEvents({
    once: () => {
        console.log("只會(huì)console一次");
        myEvents.removeEvent("once");
    },
    infinity: () => {
        console.log("每次點(diǎn)擊,都會(huì)console");
    }
});

document.onclick = e => {
    myEvents.fireEvents(["once", "infinity"]);
}

2.DOM自定義事件

let elImage = document.getElementById("image");
$(elImage).addEvent("click", e => {
    e = e || window.event;
    let target = e.target || e.srcElement;

    // 元素節(jié)點(diǎn) 為1; 元素屬性 為2
    if (target.nodeType === 1) {
        console.log(`點(diǎn)擊類(lèi)型:${e.type}`);
        $(target).fireEvent("console");
    }
})

2.1.nodeType:

2.2.DOM事件流:

發(fā)布/訂閱: 消息通訊

1.實(shí)現(xiàn)一個(gè)消息發(fā)布

let subPub = new SubPub();
subPub.subscribe("getName", name => {
    console.log("your name is: ", name);
});
subPub.publish("getName", "Tom");

1.觀察者模式和發(fā)布/訂閱的區(qū)別:

1.1.Observer模式要求希望接收到主題通知者的觀察者必須訂閱內(nèi)容改變的事件

1.2.Subscribe/Publish模式使用了一個(gè)主題/事件通道,這個(gè)通道介于訂閱者和發(fā)布者之間。該事件系統(tǒng)允許代碼定義應(yīng)用程序的特定事件,該事件可以傳遞自定義參數(shù),自定義參數(shù)包含訂閱者所需要的值。其目的是避免訂閱者和發(fā)布者產(chǎn)生依賴關(guān)系。

from: 《Javascript設(shè)計(jì)模式》

2.nodejs版本的消息發(fā)布、訂閱

const EventEmitter = require("events");

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on("event", (a, b) => {
  console.log(a, b, this);
});
myEmitter.emit("event", "a", "b");

2.1.ES6中import對(duì)于循環(huán)引用的處理問(wèn)題

TODO: require引用?

2.2.?commonJS中require是值的copy?,ES6中import是值的引用

3.更高級(jí)的狀態(tài)管理:redux,vuex

promise: 回調(diào)的代碼組織的封裝 1.promise A+規(guī)范: wiki、plus、A+翻譯 2.promise的流程

3.要點(diǎn)

3.1.Promise 本質(zhì)是一個(gè)狀態(tài)機(jī)。每個(gè) promise 只能是 3 種狀態(tài)中的一種:pending、fulfilled 或 rejected。狀態(tài)轉(zhuǎn)變只能是 pending -> fulfilled 或者 pending -> rejected。狀態(tài)轉(zhuǎn)變不可逆。

3.2.then 方法可以被同一個(gè) promise 調(diào)用多次。

3.3.then 方法必須返回一個(gè) promise。

4.一些問(wèn)題

4.1.下面四個(gè)使用promise語(yǔ)句的不同點(diǎn)在哪里?

doSomething().then(function () {
    return doSomethingElse();
}).then(finalHandler);

doSomething().then(function () {
    doSomethingElse();
}).then(finalHandler);

doSomething().then(doSomethingElse()).then(finalHandler);

doSomething().then(doSomethingElse).then(finalHandler);

4.2.新手問(wèn)題:

4.2.1.callback方式使用promise

// anotherPromise依賴somePromise
// 不推薦
somePromise()
.then(data => {
  anotherPromise(data.id)
  .then(anotherData => {
    // write your code here
  })
  .catch(window.console.log.bind(window.console))
})
.catch(window.console.log.bind(window.console))

// 推薦
somePromise()
.then(data => {
  return anotherPromise(data.id).then(data, anotherData);
})
then((data, another) => {

})
.catch(window.console.log.bind(window.console))

4.2.2.forEach使用promise,應(yīng)該使用Promise.all

// 不推薦
let promises = [new Promise(resolve => {
  let dataA = {
    name: "dataA"
  };
  resolve(dataA);
}), new Promise(resolve => {
  let dataB = {
    name: "dataB"
  };
  resolve(dataB);
})];
let keys = ["dataA", "dataB"]
let dataAll = {};
promises.forEach((promise, index) => {
  promise
  .then(data => {
    dataAll[keys[index]] = data;
  })
  .catch(e => {
    console.log("error: ", e);
  })
});
// 推薦
Promise
.all(promises)
.then(data => {
  // [dataA, dataB]
})

4.2.3.忘記加catch

somePromise()
.then(() => {
  return anotherPromise();
})
.then(() => {
  return lastPromise();
})
// 沒(méi)有業(yè)務(wù)錯(cuò)誤需求,加上這句就方便調(diào)試
.catch(console.log.bind(console));

4.2.3.不推薦使用deferred(歷史包袱),兩種方式改正

4.2.3.1.使用第三方的庫(kù)包裝成promise,如angular的$q庫(kù):

$q.when(db.put(doc)).then(...)

4.2.3.2.使用promise:

new Promise(function (resolve, reject) {
    fs.readFile("myfile.txt", function (err, file) {
        if (err) {
            return reject(err);
        }
        resolve(file);
    });
})
.then(...)

4.2.4.不顯示調(diào)用return

somePromise()
.then(() => {
  anotherPromise();
})
.then(data => {
  // data was undefined
})

4.3.進(jìn)階錯(cuò)誤

4.3.1.不了解Promise.resolve()/Promise.reject();

4.3.2.catch和then(null, reject => {})不完全相同: then中的rejectHandler不會(huì)捕獲resolveHandler中的錯(cuò)誤

// 1.then reject
somePromise().then(resolve => {
  throw new Error("error");
}, reject => {
  // catch nothing
})
// 2.catch: this type was recomended
somePromise()
.then(resolve => {
  throw new Error("error");
})
.catch(e => {
  // catch the error
})

// 3.the same as below:
somePromise()
.then(resolve => {
  throw new Error("error");
})
.then(null, e => {
  // catch the error
})

4.3.3.promise vs promise factories: 一個(gè)接一個(gè)執(zhí)行一系列的promise

function executeSequentially(promiseFactories) {
  var result = Promise.resolve();
  promiseFactories.forEach(function (promiseFactory) {
    result = result.then(promiseFactory);
  });
  return result;
}
// 使用promise工廠
function myPromiseFactory() {
  return somethingThatCreatesAPromise();
}
// 示例:
let promiseFactories = [];
promiseFactories.push(myPromiseFactory);
executeSequentially(promiseFactories);

4.3.4.想要兩個(gè)promise的結(jié)果

4.3.4.1.原始代碼

let getUserAndAccount = user => {
  return new Promise((resolve, reject) => {
    getUserAccountById(user.id)
    .then(userAccount => {
      resolve(user, userAccount);
    })
    .catch(reject);
  })
}
getUserByName("nolan")
.then(getUserAndAccount)
.then(function (user, userAccount) {
  console.log("user and userAccount: ", user, userAccount);
})
.cath(e => {
  console.log("error: ", e);
});

4.3.4.2.簡(jiǎn)化后代碼

let getUserAndAccount = user => getUserAccountById(user.id)
                                .then(userAccount => Promise.resolve(user, userAccount))
getUserByName("nolan")
.then(getUserAndAccount)
.then(function (user, userAccount) {
  console.log("user and userAccount: ", user, userAccount);
})
.cath(e => {
  console.log("error: ", e);
});

4.3.5.值穿透

Promise.resolve("foo").then(Promise.resolve("bar")).then(function (result) {
  console.log(result);
});

4.3.6.不能cancel?,issue70, proposal-cancelable-promises

5.一些提議

5.1.then方法內(nèi)部相關(guān):

5.1.1.return一個(gè)promise對(duì)象。

5.1.2.return一個(gè)同步值或者是undefined

5.1.3.同步的throw一個(gè)錯(cuò)誤

getUserByName("nolan").then(function (user) {
  if (user.isLoggedOut()) {
    throw new Error("user logged out!"); // throwing a synchronous error!
  }
  return inMemoryCache[user.id] || getUserAccountById(user.id);    // returning a synchronous value or a promise!
}).then(function (userAccount) {
  // I got a user account!
}).catch(function (err) {
  // Boo, I got an error!
  if (err) {
    let message = err.message;
    if (~message.indexOf("logged")) {
      // 已經(jīng)登出的處理邏輯
    } else {
      // 其他的錯(cuò)誤處理邏輯
    }
  }
});
6.一些Promise知識(shí)點(diǎn)

6.1.Promise.all, Promise.race

6.1.1.相同點(diǎn): Promise.race和Promise.all都能接收一個(gè)數(shù)組

6.1.2.不同點(diǎn): Promise.race只要有一個(gè)reject或者resolve,就立即返回,Promise.all等待所有的resolve,reject,才會(huì)返回,如果有一個(gè)reject,那么all的結(jié)果也是reject的(所有的resolve,才會(huì)resolve)

Promise.all([new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log("first");
  }, 1000);
}), Promise.reject(123), new Promise((resolve, reject) => {
  console.log("second");
  resolve();
})])
.then(data => {
  console.log("I am all data: ", data);
})
.catch(e => {
  console.log("error", e);
});

6.1.3.使用場(chǎng)景: Promise.race可以在ajax網(wǎng)絡(luò)超時(shí)判斷使用

let timeout = 3e3;
Promise.race([new Promise((resolve, reject) => {
  $.ajax("url", resp => {
    console.log("ajax resp: ", resp);
  });
}), new Promise((resolve, reject) => {
  setTimeout(resolve, timeout);
})]);

6.2.Promise.resolve返回一個(gè)已經(jīng)resolve的promise對(duì)象,reject同理

generator,yeild: 流程控制的新語(yǔ)法 1.generator的含義與定義: 異步操作的容器
function* gen(){
    let url = "https://api.github.com/users/github";
    let result = yield fetch(url);
    console.log("result: ", result.bio);
}

let genUser = () => {
    let g = gen();
    let result = g.next();

    result.value.then(data => {
        let json = data.json();
        return json;
    }).then(data => {
        g.next(data);
    });
}

1.1.函數(shù)可以暫停執(zhí)行和恢復(fù)執(zhí)行

1.2.Generator 函數(shù)可以不用yield表達(dá)式,這時(shí)就變成了一個(gè)單純的暫緩執(zhí)行函數(shù)

function* f() {
    console.log("執(zhí)行了!")
}

var generator = f();

setTimeout(function () {
    generator.next()
}, 2000);

1.3.函數(shù)體內(nèi)外的數(shù)據(jù)交換和

function* gen(x){
  var y = yield x + 2;
  console.log("gen(): ", y, x);
  return y;
}
var g = gen(1);
var value = g.next();
console.log("value: ", value);
var value2 = g.next(12);
console.log("value2: ", value2);

1.4.錯(cuò)誤處理機(jī)制

function* gen(x){
  var y;
  try{
    y = yield x + 2;
    console.log("gen(): ", y, x);
  }catch(e){
    console.log(e);
  }
  return y;
}
var g = gen(1);
var value = g.next();
console.log("value: ", value);
var value2 = g.throw(new Error("error"));

1.5.yield表達(dá)式只能用在 Generator 函數(shù)里面

function f(param) {
    let a = yield 3 * param;
}
2.Thunk函數(shù)的含義與定義: 可以在回調(diào)函數(shù)里,將執(zhí)行權(quán)交還給 Generator 函數(shù),生產(chǎn)環(huán)境推薦thunkify
var gen = function* (){
  var f1 = yield readFile("fileA");
  var f2 = yield readFile("fileB");
  // ...
  var fn = yield readFile("fileN");
};

run(gen);

2.thunk函數(shù)介紹: 誕生于上個(gè)60年代

2.1.1.傳值調(diào)用

let f = (a, b) => b;

f(3 * x * x - 2 * x - 1, x);

2.1.2.傳名調(diào)用

let f = m => m * 2;

f(x + 5);

// 等同于

let thunk () => (x + 5);

let f = thunk => (thunk() * 2);

2.1.3.thunkify源碼:

function thunkify(fn){
  return function(){
    let args = Array.prototype.slice.call(arguments);
    let ctx = this;

    return function(done){
      // 檢查機(jī)制: 確?;卣{(diào)函數(shù)只運(yùn)行一次
      let called;

      args.push(function(){
        if (called) return;
        called = true;
        done.apply(null, arguments);
      });

      try {
        fn.apply(ctx, args);
      } catch (err) {
        done(err);
      }
    }
  }
};

2.1.4.thunk與generator結(jié)合:

let fs = require("fs");
let thunkify = require("thunkify");
let readFile = thunkify(fs.readFile);

let gen = function* (){
  let r1 = yield readFile("/etc/fstab");
  console.log(r1.toString());
  let r2 = yield readFile("/etc/shells");
  console.log(r2.toString());
};

2.1.5.手動(dòng)執(zhí)行:

let g = gen();

let r1 = g.next();
r1.value(function(err, data){
  if (err) throw err;
  let r2 = g.next(data);
  r2.value(function(err, data){
    if (err) throw err;
    g.next(data);
  });
});

2.1.6.簡(jiǎn)化封裝:

function run(fn) {
  let gen = fn();

  function next(err, data) {
    let result = gen.next(data);
    if (result.done) return;
    result.value(next);
  }

  next();
}

run(gen);
3.co函數(shù)庫(kù)的含義與定義: Generator 函數(shù)的執(zhí)行器, yield后必須是thunk/promise函數(shù)
var gen = function* (){
  var f1 = yield readFile("/etc/fstab");
  var f2 = yield readFile("/etc/shells");
  console.log(f1.toString());
  console.log(f2.toString());
};

var co = require("co");
co(gen);

3.1.協(xié)程與事件循環(huán): 控制流的主動(dòng)讓出和恢復(fù)

3.1.1.提出時(shí)間: 1963; 提出人: Melvin Conway

3.1.2.歷程: 進(jìn)程->線程->用戶態(tài)線程->協(xié)程

3.1.3.名詞釋義:

3.1.3.1.進(jìn)程: 代碼,被代碼控制的資源(內(nèi)存,I/O,文件)兩大基本元素等組成的實(shí)體,兩大特性[掌控資源,可以被調(diào)度]

3.1.3.2.線程: 程在進(jìn)程內(nèi)部,處理并發(fā)的邏輯,擁有獨(dú)立的棧,卻共享線程的資源

3.1.3.3.用戶態(tài)線程: 線程切換的時(shí)候,進(jìn)程需要為了管理而切換到內(nèi)核態(tài),處理狀態(tài)轉(zhuǎn)換(性能消耗嚴(yán)重)

3.1.4.沒(méi)火的原因: 命令式編程(自頂向下開(kāi)發(fā),子歷程作為唯一控制結(jié)構(gòu))、函數(shù)式編程[意氣之爭(zhēng)]

3.1.5.關(guān)系: 子歷程是沒(méi)有使用yield的協(xié)程。Donald Ervin Knuth(wiki)/Donald Ervin Knuth(baike): 子歷程是協(xié)程的一種特例

3.2.使用co, yield后面放的必須是thunk/promise函數(shù)

async,await: generator的語(yǔ)法糖 async的含義與定義
let getData = () => {
    return new Promise((resolve, reject) => {
        $.ajax({
            url: "json/test.json",
            method: "GET",
            success: function (resp) {
                // data = resp.data;
                resolve(resp);
            },
            error: function (error) {
                reject(error);
            }
        });
    });
}

async function initView(){
    try {
        let resp = await getData();
        console.log(resp);
    } catch (e) {
        console.error(e);
    }
}
initView();
async的一些問(wèn)題

1.同時(shí)觸發(fā):

// 寫(xiě)法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);

// 寫(xiě)法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
最后的一些問(wèn)題與思考

1.從異步操作上,async是最后演化的結(jié)果,callback是就不用了、還是應(yīng)該盡量避免?

參考資料

Node.js最新技術(shù)棧之Promise篇

Promise實(shí)現(xiàn)原理

詳解ES6 中的Promise與異步編程

深入Promise

你可能不知道的Promise

談?wù)勈褂胮romise時(shí)候的一些反模式(EFE)

Promise Demo Implement

Promise Demo Implement for Question

JavaScript Promise迷你書(shū)(中文版)

mdn Promise

JavaScript Promises ... In Wicked Detail

JavaScript異步編程原理

深入掌握ECMAScript 6 異步編程系列(阮一峰)

漫談js自定義事件、DOM/偽DOM自定義事件(張?chǎng)涡?

js原生創(chuàng)建模擬事件和自定義事件

JS觀察者模式

NodeJS Event

NodeJS EventEmitter

JS發(fā)布/訂閱簡(jiǎn)單實(shí)現(xiàn)

擴(kuò)展閱讀

JS函數(shù)式編程指南

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/83679.html

相關(guān)文章

  • jQuery 源碼系列(七)Callbacks 函數(shù)

    摘要:的支持的方法有幾個(gè)主要的,和,比如官方有一個(gè)例子這兩個(gè)作為函數(shù)調(diào)用的生成從基本可以看出,函數(shù)生成了一個(gè)對(duì)象,這個(gè)對(duì)象的方法是添加回調(diào)函數(shù),而方法則是執(zhí)行回調(diào)函數(shù)。 歡迎來(lái)我的專(zhuān)欄查看系列文章。 講真,Sizzle 的源碼真的太壓抑了,以至于寫(xiě) Sizzle 文章的這段時(shí)間里都非常的痛苦,剛開(kāi)始覺(jué)得它還挺有意思的,越到后面越覺(jué)得代碼很難讀懂,煩。 寒假也過(guò)完了,在家里待了兩周的時(shí)間,感覺(jué)...

    timger 評(píng)論0 收藏0
  • promise源碼解析

    摘要:源碼參考主要內(nèi)容的迭代設(shè)計(jì)中主要的代碼片段,翻譯一部分加上自己的理解,同時(shí)指出的一些特性。先貼完整代碼安全性和穩(wěn)定性保證和在未來(lái)他們被調(diào)用的時(shí)候,應(yīng)該是和注冊(cè)時(shí)的順序是保持一致的。這將顯著降低異步編程中流程控制出錯(cuò)可能性。 源碼參考https://github.com/kriskowal/...主要內(nèi)容:promise的迭代設(shè)計(jì)中主要的代碼片段,翻譯一部分加上自己的理解,同時(shí)指出pro...

    kamushin233 評(píng)論0 收藏0
  • 帶你徹底弄懂Event Loop

    前言 我在學(xué)習(xí)瀏覽器和NodeJS的Event Loop時(shí)看了大量的文章,那些文章都寫(xiě)的很好,但是往往是每篇文章有那么幾個(gè)關(guān)鍵的點(diǎn),很多篇文章湊在一起綜合來(lái)看,才可以對(duì)這些概念有較為深入的理解。 于是,我在看了大量文章之后,想要寫(xiě)這么一篇博客,不采用官方的描述,結(jié)合自己的理解以及示例代碼,用最通俗的語(yǔ)言表達(dá)出來(lái)。希望大家可以通過(guò)這篇文章,了解到Event Loop到底是一種什么機(jī)制,瀏覽器和Nod...

    hersion 評(píng)論0 收藏0
  • 二叉樹(shù)遍歷

    摘要:前言本篇文章是在二叉排序樹(shù)的基礎(chǔ)上進(jìn)行遍歷查找與刪除結(jié)點(diǎn)。接下來(lái)我們根據(jù)構(gòu)造的這顆二叉樹(shù)進(jìn)行相應(yīng)遍歷查找與刪除操作。遍歷二叉樹(shù)二叉樹(shù)的遍歷分為深度優(yōu)先遍歷和廣度優(yōu)先遍歷。中序遍歷二叉排序樹(shù),得到的數(shù)組是有序的且是升序的。 前言 本篇文章是在二叉排序樹(shù)的基礎(chǔ)上進(jìn)行遍歷、查找、與刪除結(jié)點(diǎn)。 那么首先來(lái)看一下什么是二叉排序樹(shù)? 二叉排序樹(shù) 定義 二叉排序樹(shù),又稱(chēng)二叉查找樹(shù)、二叉搜索樹(shù)。 若...

    aboutU 評(píng)論0 收藏0
  • 帶你讀Backbone源碼解讀之Events實(shí)現(xiàn)

    摘要:接受個(gè)參數(shù),包括事件的名稱(chēng),回調(diào)函數(shù)和回調(diào)函數(shù)執(zhí)行的上下文環(huán)境。保留回調(diào)函數(shù)在數(shù)組中取出對(duì)應(yīng)的以及中的函數(shù)。當(dāng)然,你同樣可以在綁定的回調(diào)函數(shù)執(zhí)行前手動(dòng)通過(guò)將其移除。 Backbone源碼解讀 Backbone在流行的前端框架中是最輕量級(jí)的一個(gè),全部代碼實(shí)現(xiàn)一共只有1831行1。從前端的入門(mén)再到Titanium,我雖然幾次和Backbone打交道但是卻對(duì)它的結(jié)構(gòu)知之甚少,也促成了我想讀...

    AndroidTraveler 評(píng)論0 收藏0
  • tornado 源碼閱讀-初步認(rèn)識(shí)

    摘要:序言最近閑暇無(wú)事閱讀了一下的源碼對(duì)整體的結(jié)構(gòu)有了初步認(rèn)識(shí)與大家分享不知道為什么右邊的目錄一直出不來(lái)非常不舒服不如移步到吧是的核心模塊也是個(gè)調(diào)度模塊各種異步事件都是由他調(diào)度的所以必須弄清他的執(zhí)行邏輯源碼分析而的核心部分則是這個(gè)循環(huán)內(nèi)部的邏輯貼 序言 最近閑暇無(wú)事,閱讀了一下tornado的源碼,對(duì)整體的結(jié)構(gòu)有了初步認(rèn)識(shí),與大家分享 不知道為什么右邊的目錄一直出不來(lái),非常不舒服. 不如移...

    2450184176 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<