Async/Await(异步处理)

async/await async 是Generator函数的语法糖,并对Generator函数进行了改进。ES7 版本中引入
一个线程(或函数)执行到一半,可以暂停执行,将执行权交给另一个线程(或函数),等到稍后收回执行权的时候,再恢复执行。这种可以并行执行、交换执行权的线程(或函数),就称为协程。

协程是一种比线程更加轻量级的存在。
普通线程是抢先式的,会争夺cpu资源,而协程是合作的,可以把协程看成是跑在线程上的任务,一个线程上可以存在多个协程,但是在线程上同时只能执行一个协程。
// async/await

async getBooksByAuthorWithAwait(authorId) {
    const books = await bookModel.fetchAll();  
    return books.filter(b => b.authorId === authorId);
}

// promise
getBooksByAuthorWithPromise(authorId) { 
    return bookModel.fetchAll().then(books => books.filter(b => b.authorId === authorId));
}
async/await 是线性的,更容易理解, 调试的时候更加方便

缺点 会造成代码阻塞,导致性能问题
过于线性化

async getBooksAndAuthor(authorId) {  
    const books = await bookModel.fetchAll();  
    const author = await authorModel.fetch(authorId);  
    return {    
        author,    
        books: books.filter(book => book.authorId === authorId),  
    };
}

// 请求没有依赖关系,过于线性化,请求时间过长


async getBooksAndAuthor(authorId) {  
    const bookPromise = bookModel.fetchAll();  
    const authorPromise = authorModel.fetch(authorId);  
    const book = await bookPromise;  
    const author = await authorPromise;  
    return {    
        author,    
        books: books.filter(book => book.authorId === authorId),  
    };
}

// 没有依赖关系,正确使用方式
错误处理方式

方式一 try...catch

class BookModel {  
    fetchAll() {    
        return new Promise((resolve, reject) => {      
            window.setTimeout(() => { 
                reject({'error': 400}) 
            }, 1000);    
        });  
    }
}

// async/await
async getBooksByAuthorWithAwait(authorId) {
    try {  
        const books = await bookModel.fetchAll();
    } catch (error) {  
        console.log(error);    // { "error": 400 }
    }
}

优点  方便,简单
     可以集中处理,所有错误

缺点 不能准确定位错误的位置
class BookModel {  
    fetchAll() {    
        cb();    // note `cb` is undefined and will result an exception    
        return fetch('/books');  
    }
}

try {  
    bookModel.fetchAll();
} catch(error) {  
    console.log(error);  // This will print "cb is not defined"
}
方式二 catch

// books === undefined if error happens,
// since nothing returned in the catch statement
let books = await bookModel.fetchAll().catch((error) => {
        console.log(error); 
    });
方式三 await-to-js

/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
export function to<T, U = Error> (
  promise: Promise<T>,
  errorExt?: object
): Promise<[U | null, T | undefined]> {
  return promise
    .then<[null, T]>((data: T) => [null, data])
    .catch<[U, undefined]>((err: U) => {
      if (errorExt) {
        Object.assign(err, errorExt);
      }


      return [err, undefined];
    });
}

export default to;



  
import to from '../../dist';


const UserModel = {
  findById: (userId) => {
    return new Promise((resolve, reject) => {
      if(userId) {
        const userObjet = {
          id: userId,
          notificationsEnabled: true
        };
        return resolve(userObjet);
      }
      reject('Data is missing');
    });
  }
};


const TaskModel = function ({userId, name}) {
  return new Promise((resolve, reject) => {
    if(userId && name) {
      const newTask = {
        assignedUser: {
          id: userId
        }
      };
      return resolve(newTask);
    }
    reject('Data is missing');
  });
};


const NotificationService = {
  sendNotification: (userId, name) => {
    return new Promise((resolve, reject) => {
      if(userId && name) return resolve('Success');
      reject('Data is missing');
    });
  }
};


async function asyncTask(userId, cb) {
  let err, user, savedTask, notification;
  [ err, user ] = await to(UserModel.findById(userId));
  if(!(user && user.id)) return cb('No user found');


  [ err, savedTask] = await to(TaskModel({userId: user.id, name: 'Demo Task'}));
  if(err) return cb('Error occurred while saving task');


  if(user.notificationsEnabled) {
    [ err ] = await to(NotificationService.sendNotification(user.id, 'Task Created'));
    if(err) return cb('Error while sending notification');
  }


  if(savedTask.assignedUser.id !== user.id) {
    [ err, notification ] = await to(NotificationService.sendNotification(savedTask.assignedUser.id, 'Task was created for you'));
    if(err) return cb('Error while sending notification');
  }

  cb(null, savedTask);
}


asyncTask(1, (err, newTask) => {
  console.log('new task created');
  console.log(err);
  console.log(newTask);
});


asyncTask(null, (err, newTask) => {
  console.log('fail');
  console.log(err);
  console.log(newTask);
});



interface ServerResponse {
  test: number;
}

const p = Promise.resolve({test: 123});

const [err, data] = await to<ServerResponse>(p);
console.log(data.test);
for(fname of files) {
     let fcontent = await read(fname)}
for(idx in files) {
     let fcontent = await read(files[idx])
 }
files.forEach( async fname => {
    let fcontent = await read(fname)
})
const mapLoop = async _ => {
  console.log('Start');

  const promises = fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit;
  });

  const numFruits = await Promise.all(promises);
  console.log(numFruits);

  console.log('End')
}
filter  回调中使用await时,回调总是一个promise。由于promise 总是真的,数组中的所有项都通过filter;

先map处理完数据后,正常使用filter即可

reduce 同样的道理 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值